1

I am using following code to update a modal in my view and then replacing the content using controller action.

 $('#myTable1, #myTable2').on('click', 'a.editor_edit', function (e) {
            e.preventDefault();

            //console.log(e.target);
            //console.log(this.closest('table'));


            var passedId = $(this).attr("id");
            //console.log(passedId);

            $.get('/Controller/EditCustomer/' + passedId, function (data) {
                console.log(data);
                $('#partial').replaceWith(data);
                $('#reportModal').modal('show');
            });

        });

But when the modal appears , it still holds the data for the 1st id. And it never updates the content inside modal.

I suspect it is either the modal or I am displaying the modal too soon (before replace complete).

When I do a console.log , I get new data each time though...

In Index.cshtml , I have this .

<div id="partial" style="display: none">

</div>

And the partial view looks like ,

@model MyModel

<div class="modal fade" id="reportModal" tabindex="-1" role="dialog" aria-labelledby="reportModalLabel">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&#xD7;</span></button>
                <h4 class="modal-title" id="reportModalLabel">Edit Customer:</h4>
                @if (Model != null)
                {
                    using (Html.BeginForm())
                    {
                        @Html.AntiForgeryToken()

                        <div class="form-horizontal">
                            <h4>Customer</h4>
                            <hr />
                            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                            @Html.HiddenFor(model => model.ID)

                            <div class="form-group">
                                @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
                                <div class="col-md-10">
                                    @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                                    @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
                                </div>
                            </div>

                            <div class="form-group">
                                @Html.LabelFor(model => model.Description, htmlAttributes: new { @class = "control-label col-md-2" })
                                <div class="col-md-10">
                                    @Html.EditorFor(model => model.Description, new { htmlAttributes = new { @class = "form-control" } })
                                    @Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })
                                </div>
                            </div>

                            <div class="form-group">
                                <div class="col-md-offset-2 col-md-10">
                                    <input type="submit" value="Save" class="btn btn-default" />
                                </div>
                            </div>
                        </div>
                    }

                }
            </div>
            <div class="modal-body">
                <canvas id="reportsChart" width="400" height="400"></canvas>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" id="modal-cancel-b">Cancel</button>
                <button type="button" class="btn btn-primary"  aria-haspopup="true" aria-expanded="false">Save</button>
            </div>
        </div>
    </div>
</div>
Simsons
  • 12,295
  • 42
  • 153
  • 269
  • We need more information including the relevant html –  Jan 31 '18 at 01:58
  • And since your using `replaceWith()`, does the partial you return also include an element with `id="partial"`? (I suspect you probably want `$('#partial').html(data);`) –  Jan 31 '18 at 02:03
  • No the partial I am returning does no include element with id partial – Simsons Jan 31 '18 at 02:05
  • Then you need `$('#partial').html(data);` (I'll add an answer explaining why shortly) –  Jan 31 '18 at 02:08
  • Did edit the question and .html comes back with blank popup – Simsons Jan 31 '18 at 02:08
  • 1
    `replaceWith()` replaces the element with the partial so the first time it should work. But because the `
    ` element no longer exists, then the second time you call `$('#partial').replaceWith(data);` it wont do anything - there is no longer an element with `
    `
    –  Jan 31 '18 at 02:11
  • If your getting a 'blank' popup, then it suggests other issues (but you stated the `console.log(data)` is showing what you expect?) –  Jan 31 '18 at 02:12
  • Yes, Console.log show correct data... – Simsons Jan 31 '18 at 02:13
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/164219/discussion-between-stephen-muecke-and-simsons). –  Jan 31 '18 at 02:13
  • Remove `style="display: none"` from the `
    `
    –  Jan 31 '18 at 02:17
  • @StephenMuecke, removing display none and doing .html(data) worked. This can be the answer. – Simsons Jan 31 '18 at 03:03

1 Answers1

2

replaceWith() replaces the element that your selecting, so the first time you execute your script, the <div id="partial"> element is replaced with your partial view. But because the partial does not contain an enclosing element with id="partial", the next time you execute the script, your $('#partial').replaceWith(data); does nothing because there is no longer an element with id="partial" in the DOM.

Instead you need to use $('#partial').html(data); which replaces the contents of the element rather than the element itself.

You also need to remove the style="display: none" from the element (or use .show() to make it visible in the ajax callback, although there seems no reason to make it hidden)

The ajax call should be

$.get('/Controller/EditCustomer/' + passedId, function (data) {
    console.log(data);
    $('#partial').html(data);
    $('#reportModal').modal('show');
});

although its always preferred to use @Url.Action() to generate urls

$.get('@Url.Action("EditCustomer", "Controller")' { id: passedId }, function (data) {

There are some other issues with your code to consider

  1. You currently will not get any client side validation, so you need to re-parse the $.validator in the success callback - refer Required field validations not working in JQuery Popup MVC 4
  2. You can improve performance by including the partial in the view initially (say using @Html.Partial("yourPartialName", new MyModel())) and having your method returning a JsonResult of the MyModel instance, which you can then use to update the form controls. Not only would you be sending far less data back to the client, you would not need to re-parse the $.validator which is expensive. And if all the property values are already in the DOM (e.g. as columns of your tables), then you would not need any ajax call (just update the form controls from those values)
  3. You also need to consider what happens of ModelState is invalid in the controller POST method and how you handle returning the view