动态添加部分视图后如何重新初始化JQuery

Posted

技术标签:

【中文标题】动态添加部分视图后如何重新初始化JQuery【英文标题】:How to reinitialise JQuery after partial view dynamically added 【发布时间】:2014-07-21 17:10:27 【问题描述】:

我正在使用以下代码从我的 MVC 表单中动态添加和删除部分视图。我的问题是部分视图包含一个我使用 Select2 的下拉列表。当我添加一个新的局部视图项时,不会调用 Select2 初始化程序。

在我的主要形式中:

@html.LinkToAddNestedForm(m => m.QuoteItemViewModels, "Add Item ", "#quoteItems tbody", ".quoteItem", "QuoteItemViewModels")

我的辅助函数:

public static MvcHtmlString LinkToAddNestedForm<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string linkText, string containerElement, string counterElement, string cssClass = null) where TProperty : IEnumerable<object>
    
        // a fake index to replace with a real index
        //long ticks = DateTime.UtcNow.Ticks;
        string fakeIndex = Guid.NewGuid().ToString();
        // pull the name and type from the passed in expression
        string collectionProperty = ExpressionHelper.GetExpressionText(expression);
        var nestedObject = Activator.CreateInstance(typeof(TProperty).GetGenericArguments()[0]);

        // save the field prefix name so we can reset it when we're doing
        string oldPrefix = htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix;
        // if the prefix isn't empty, then prepare to append to it by appending another delimiter
        if (!string.IsNullOrEmpty(oldPrefix))
        
            htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix += ".";
        
        // append the collection name and our fake index to the prefix name before rendering
        htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix += string.Format("0[1]", collectionProperty, fakeIndex);
        string partial = htmlHelper.EditorFor(x => nestedObject).ToHtmlString();

        // done rendering, reset prefix to old name
        htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix = oldPrefix;

        // strip out the fake name injected in (our name was all in the prefix)
        partial = Regex.Replace(partial, @"[\._]?nestedObject", "");

        // encode the output for javascript since we're dumping it in a JS string
        partial = HttpUtility.JavaScriptStringEncode(partial);

        // create the link to render
        var js = string.Format("javascript:addNestedForm('0','1','2','3');return false;", containerElement, counterElement, fakeIndex, partial);
        TagBuilder a = new TagBuilder("a");
        a.Attributes.Add("href", "javascript:void(0)");
        a.Attributes.Add("onclick", js);
        if (cssClass != null)
        
            a.AddCssClass(cssClass);
        
        a.InnerHtml = linkText;

        return MvcHtmlString.Create(a.ToString(TagRenderMode.Normal));
    

我的 JS:

function addNestedForm(container, counter, ticks, content) 
    //var nextIndex = $(counter).length;
    var nextIndex = $(container + " " + counter).length;
    var pattern = new RegExp(ticks, "gi");
    content = content.replace(pattern, nextIndex);
    $(container).append(content);

    resetValidation();


function resetValidation() 
    // can't add validation to a form, must clear validation and rebuild
    $("form").removeData("validator");
    $("form").removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse("form");


我的部分观点:

<tr class="quoteItem">

<td style="padding:1px">

    @Html.DropDownListFor(
     x => x.QuoteItem.Location,
                Model.LocationTypes, "", new  @style = "width:100px", @class = "ddl" )
    @Html.ValidationMessageFor(model => model.QuoteItem.Location)
</td>
<td style="padding:1px">
    @Html.TextBoxFor(x => x.QuoteItem.Area, new  style = "width:100px;height:35px" )
</td>

</tr>

我在从我的 layout.cshtml 中的包加载的 js 文件中使用以下代码初始化 Select2:

$(document).ready(function () 

    $(".ddl").select2();

);

这适用于我的第一个项目,但不适用于随后创建的任何项目。

【问题讨论】:

尝试在主表单文档就绪函数中初始化ddl 我已经这样做了 - 我已经编辑了我的问题以包含这些详细信息。 【参考方案1】:

$(document).ready()DOM 完全加载后触发,因为它是第一次来自服务器,因此在添加/删除节点时不会触发对应于您的局部视图,因为您正在修改树,而不是再次加载它。

然后,您所要做的就是确保在添加局部视图的 DOM 节点后执行 $(".ddl").select2() 。无需重新初始化 JQuery 即可。

如果我是你,我会添加 $(".ddl").select2();到 addNestedForm() 函数的末尾。

function addNestedForm(container, counter, ticks, content) 
    //var nextIndex = $(counter).length;
    var nextIndex = $(container + " " + counter).length;
    var pattern = new RegExp(ticks, "gi");
    content = content.replace(pattern, nextIndex);
    $(container).append(content);

    resetValidation();

    $(".ddl").select2();

另一种解决方案是添加一个侦听器,如本文所示: Is there a JavaScript/jQuery DOM change listener?

【讨论】:

绝对正确,但要真正获得赏金/接受的答案,请添加示例代码。祝你好运。 谢谢,这似乎是有道理的,除非我添加 $(".ddl").select2();到 addNestedForm() 函数的末尾,然后单击“添加项目”,我在控制台中收到以下错误:未为 Select2 s2id_QuoteItemViewModels_0__QuoteItem_Location 定义未捕获的查询函数 @RobbieMills,这很有趣。您能否将您的 select2() 方法添加到您的原始帖子中? @RobbieMills,你可能想看看这个帖子***.com/questions/14483348/… 感谢@dsnunez,该帖子以及您的示例有所帮助。

以上是关于动态添加部分视图后如何重新初始化JQuery的主要内容,如果未能解决你的问题,请参考以下文章

Bootstrap Select - 在动态添加的元素上重新初始化

如何jquery实现表格数据的动态添加与统计

jquery给表格动态添加删除行后如何获取数据

用Jquery的append事件动态添加控件,点击添加时会清空原来动态控件中的值。是啥原因?

寻找一种将更多列表动态添加到 jQuery Mobile 列表视图底部的方法

jQuery动态增加表格tr时,用的是append()函 bootstrap时间控件失效的问题