0

So I have an ASP.NET MVC View that holds two partial views. Those partial views get loaded dyamically via ajax calls to controller methods. This happens when the user changes the date via calendar popup. Those partial views also contain another partial view that is dynamically loaded via an ajax call also. The problem is that my click events will not work in my most inner partial view if the outer partial view changes via ajax. In the code below I have

    $("input[name=cancelProduct]").on('click', function() {
            $("#manageProductDialog").data("kendoWindow").close();
    });

This does not work when I change the date since ManageProduct.cshtml is being generated dynamically. So I've tried these also

    $("#productView").on('click', 'input[name=cancelProduct]', function(e) {
        $("#manageProductDialog").data("kendoWindow").close();
    });

    $("#manageProductDialog").on('click', 'input[name=cancelProduct]', function(e) {
        $("#manageProductDialog").data("kendoWindow").close();
    });

These do not work either. Anyone got any ideas? Below are all my views/partial views.

Index.cshtml

    <input id="calendar" style="width:0px;" />
    <input type="button" value="Search Date" id="datePicker" />

    <ul>
        <li><div id='productView'>@Html.Partial("ProductList")</div></li>
        <li><div id='categoryView'>@Html.Partial("CategoryList")</div></li>
    </ul>

    <script type='text/javascript'>
    $("document").ready(function() {
        $("#calendar").kendoDatePicker({ });

        $("#calendar").data("kendoDatePicker").value('@DateTime.Now.ToShortDateString()');
        $("#datePicker").on('click', function() {
            $("#calendar").data("kendoDatePicker").open();
        });

        $("#calendar").on('change', function() {
            $.ajax({
              type: 'POST',
              url: serverRoot + 'Product/ViewProducts',
              data: { searchDate: $("#calendar").val() },
              success: function(data) {
                 $("#productView").html(data);
              }
            });

           $.ajax({
              type: 'POST',
              url: serverRoot + 'Category/ViewCategories',
              data: { searchDate: $("#calendar").val() },
              success: function(data) {
                 $("#categoryView").html(data);
              }
            });
        });
    });
    </script>

ProductList.cshtml

    @model IList<Stuff.Web.Models.ProductVM>

    <a id='addProduct' href='#'>Add Product</a>

    @if (Model != null && Model.Count > 0)
    {
        <table class='grid'>
            <tr>
                <td>Name</td>
                <td>Price</td>
                <td>&nbsp;</td>
            </tr>

            for (int i = 0; i < Model.Count; i++)
            {
                <tr>
                    <td>@Model[i].Name</td>
                    <td>@Model[i].Price</td>
                    <td>
                        <a id='edit_@Model[i].Id' class='edit'>Edit</a>
                        <a id='remove_@Model[i].Id' class='remove'>Remove</a>
                    </td>
                </tr>
            }
        </table>
    }
    <div id='manageProductDialog' style='display:none;'></div>

    <script type='text/javascript'>
        var manageProductDialog = $("#manageProductDialog");

        if (!manageProductDialog.data("kendoWindow")) {
            manageProductDialog.kendoWindow({
                width: "700px",
                height: "550px",
                modal: true
            });
        };

        $("#addProduct").on('click', function(e) {
            e.preventDefault();

            manageProductDialog
            .data("kendoWindow")
            .title("Add Product")
            .content("Loading Page...")
            .center()
            .open()
            .refresh({
                url: '@Url.Action("ManageProduct", "Product")'
            });

            return false;
        });
    </script>

ManageProduct.cshtml

    @model Stuff.Web.Models.ProductVM

    @using (Ajax.BeginForm("ManageProduct", "Product", new AjaxOptions {
        OnSuccess = "submitSuccess",
        Failure = "submitFailure
    }))
    {
        @Html.HiddenFor(x => x.Id)

        <table class='form'>
            <tr>
                <td>@Html.Label("Name"):</td>
                <td>@Html.EditorFor(x => x.Name)</td>
            </tr>

            <tr>
                <td>@Html.Label("Price"):</td>
                <td>@Html.EditorFor(x => x.Price)</td>
            </tr>
            <tr>
                <td colspan='2'>
                    <input type='submit' value="Save" />
                    <input type='button' name='cancelProduct' value="Cancel" />
                </td>
            </tr>
        </table>
    }

    <script type='text/javascript'>
        $("input[name=cancelProduct]").on('click', function() {
            $("#manageProductDialog").data("kendoWindow").close();
        });
    </script>
RiceRiceBaby
  • 1,546
  • 4
  • 16
  • 30
  • 1
    Try with **document**: `$(document).on('click', 'input[name=cancelProduct]'` – leonardo_palma Oct 28 '15 at 16:27
  • Nope. Only works once when the form is first loaded. Once the form gets dynamically generated via date change, it stops working. Thanks though. – RiceRiceBaby Oct 28 '15 at 16:29
  • [Event binding on dynamically created elements?](http://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements?rq=1) – Andreas Oct 28 '15 at 16:30
  • Yes I've read that article. Does not help. Thats why I created a new post since mine is slightly different with my button being dynamically generated within a form thats dynamically generated itself. – RiceRiceBaby Oct 28 '15 at 16:32
  • 2
    You shouldn't have javascript in your partial views, you should move it all to the parent view. – JB06 Oct 28 '15 at 16:33
  • Agree to disagree. Having all javascript in your parent introduces repeat of code. If I have multiple views that use the same partial view, that means I'd have to paste that same javascript in all those parent views. Keeping javascript in the partial prevents that duplication of code. – RiceRiceBaby Oct 28 '15 at 16:36
  • Once you outer view loads it binds the click events. When the inner view reloads it is not rebinding. You just need to wrap those click events in a function and call that function again when the views are reloaded. If that happens in an inner view then just broadcast an event that the outer view containing the function listens to. – Stephen Brickner Oct 28 '15 at 16:43
  • 2
    @RandomAsianGuy If you are worried about that then put the code in a separate javascript file. I find that javascript in partials almost always causes issues. – JB06 Oct 28 '15 at 16:51
  • Stephen - thanks! I see what you are saying. Can you provide an example of your advice? @JB - If i move my javascript to to a separate file, I won't have access to razor anymore. I use separate javascript files for functions that are constantly being reused. – RiceRiceBaby Oct 28 '15 at 17:40
  • You could also just try wrapping the js code in your partials with a doc ready – JB06 Oct 28 '15 at 18:10
  • @leonardo_palma: Binding to `document` is the brute-force approach. It technically solves the issue by moving the delegation to a broader (broadest, in fact) scope, but one could simply bind to the parent of the parent and achieve the same, without the more drastic negative effects of binding to `document`. – Chris Pratt Oct 28 '15 at 18:12
  • Hi all. I actually want the responsive UI route (KnockoutJS). It really is amazing and wish I had learned about this earlier. It makes writing javascript 1000 times easier. Things I've written in jquery that took hundreds of lines of code, I got it down to 10 lines of code in KnockoutJS. – RiceRiceBaby Dec 08 '15 at 05:28

0 Answers0