Hello. Here I solved the problem with connecting the "js" code to a partial view but did not stop there and found the following problem for myself. If you connect "js" on the main page ("_ Layout.cshtml") then the code is available when you first load the page, but after updating (loading using ajax) it stops working, if you connect in a partial view, the situation is reversed, and connect the script twice somehow wrong. So the question itself: What do you do in this case?

Upd:

javascript

$('.select2').each(function () { var url = this.dataset.url; $(this).select2({ delay: 100, allowClear: true, minimumInputLength: 1, // minimumInputLength for sending ajax request to server width: 'resolve', // to adjust proper width of select2 wrapped elements ajax: { url: url, type: "GET", dataType: 'json', data: function (term) { return { searchStr: term, }; }, results: function (data) { return { results: data.list }; // data.CountryList returning json data from Controller } } }) }) 

partial view

 <div id="tabItems"> @using (Ajax.BeginForm("AddOrderItem", "Order", null, new AjaxOptions { UpdateTargetId = "tabItems", HttpMethod = "Post" }, new { id = "AddItem" })) { @Html.AntiForgeryToken() <div class="nav"> <div class="navbar-form navbar-left"> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) @Html.HiddenFor(model => model.OrderId, new { id="OrderId" }) <div class="form-group"> @Html.EditorFor(model => model.ProductId, new { htmlAttributes = new { id = "ProductId", @class = "form-control select2", data_url = @Url.Action("GetProductList", "Order"), data_placeholder = "Select a product" } }) @Html.ValidationMessageFor(model => model.ProductId, "", new { @class = "text-danger" }) </div> <div class="form-group"> @Html.EditorFor(model => model.ProductNodeId, new { htmlAttributes = new { id = "ProductNodeId", @class = "form-control select2", data_url = @Url.Action("GetProductNodeList", "Order") } }) @Html.ValidationMessageFor(model => model.ProductNodeId, "", new { @class = "text-danger" }) </div> <div class="form-group"> @Html.EditorFor(model => model.ToolId, new { htmlAttributes = new { id="ToolId", @class = "form-control select2", data_url = @Url.Action("GetToolList", "Order") } }) @Html.ValidationMessageFor(model => model.ToolId, "", new { @class = "text-danger" }) </div> <div class="form-group"> @Html.EditorFor(model => model.AmountRequired, new { htmlAttributes = new { id="AmountRequired", @class = "form-control" } }) @Html.ValidationMessageFor(model => model.AmountRequired, "", new { @class = "text-danger" }) </div> <div class="form-group"> <a href="#" id="submit" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></a> </div> </div> </div> } </div> 

controller code

 public ActionResult AddOrderItem(AddOItemModel model) { //здесь какой то код return RedirectToAction("GetOrderItems", new {orderId = model.OrderId}) } public ActionResult GetOrderItems(int orderId) { var model=//получение модели для представления return PartialView("Items",model) } 

UPD2: the script took this form

 $('body').on('click', '.select2', function () { $(this).each(function () { var url = this.dataset.url; $(this).select2({ delay: 100, allowclear: true, minimuminputlength: 1, // minimuminputlength for sending ajax request to server width: 'resolve', // to adjust proper width of select2 wrapped elements ajax: { url: url, type: "get", datatype: 'json', data: function (term) { return { searchstr: term, }; }, results: function (data) { return { results: data.list }; // data.countrylist returning json data from controller } } }) }) }) 
  • Do I understand correctly: do you redraw the html part and after that stop running JS for this html part? - Kirill Ermolov
  • Yes, you understood me correctly. there is a block <div id = "Result"> </ div> which is updated as follows @ Ajax.ActionLink ("Method", "Controller", new AjaxOption {UpdateTargetId = "Result"}); - Bald
  • I think in this matter it is absolutely not important how your HTML is updated. Obviously Problem in JS . Please give an example of your JavaScript and a piece of HTML that is inserted into the markup. - Kirill Ermolov
  • updated the question, javascript led as it is. those. I have it written in the tabItems.js file - Bald

1 answer 1

Who is guilty:

The code $('.select2') returns a list of jQuery objects that internally have a link to an object (node) from the DOM ( Document Object Model ). The function that you described in each is applied to these objects.

After updating part of HTML with ajax, all DOM objects in this part of HTML are re-created and, accordingly, your function from each does not apply to them. And those objects to which you have applied your function disappeared without a trace.

In fact, not completely without a trace, such things can lead to memory leaks in JavaScript and other interesting consequences, but for a small application you can close your eyes to this.

What to do:

The most obvious solution to the problem: do not write code depending on the objects that can be re-created.

For example, if you need to subscribe to an event instead of the code:

$('.select2').on('click', function (){...})

better to use:

$('body').on('click', '.select2', function (){...})

Such code will make life easier not only for you, but also for the browser, since it will need to add only one event handler and not several (for each element '.select2' ) as in the case of $('.select2') .

How to connect widgets:

If the widget doesn’t show itself before the user starts performing actions on the element, then you can connect the widget to a specific event, for example:

 $('body').on('click', '.select2', function (e){ $(e.target).select2(); }) 

But this option is suitable if the widget normally handles situations of double connection to one element. But as far as I understand your widget does not belong to such. select2 will throw an error . You can bypass it like this:

 $('body').on('click', '.select2', function (e){ var $target = $(e.target); if (!$target.data('select2')) { $target.select2(); } }) 

If you need to connect the widget immediately after updating the part of HTML , I recommend that you put the code into a separate function that will cause the widgets to initialize and call this function every time after updating the HTML with ajax .

Somewhere in _Layout.cshtml :

 MY_APP.init_select2 = function () { $('.select2').each(function () {/* Ваш код */}) } 

where MY_APP is a global variable.

In partial view:

 <script>MY_APP.init_select2();</script> 

Unless of course there is no other way to learn about updating a piece of HTML right in JS .

The answer turned out great, I hope there is not enough water and obvious things.

  • thank you very much. very helpful. And you can advise some book for level 0 to get acquainted with the recommendations on how to write code. - Bald
  • I find it difficult to answer this question, since I myself studied JS by trial and error. But I’ll leave a couple of links anyway: Course in JS , and only in JS . Yes, if you are attracted to the format of online courses, visit these platforms: tuts + , treehouse , codeschool . Well, a classic for reading how browsers work is a big, tedious but useful article, JS Patterns by Addy Osmani , Expressive JavaScript - Kirill Ermolov