局部视图在ajax重新加载时无法正常呈现

3

我遇到了使用ajax重新加载局部视图的问题。

我的国家表单在一个局部视图中,最初当我加载主页面时,所有内容都可以正常渲染。

如下图所示,我可以使用自动完成搜索国家,并从下拉框中选择国家(两者均为kendo-mvc控件):

enter image description here

问题出现在我从自动完成中选择一个国家并尝试通过ajax加载所选国家的信息时。表单被重新加载,信息被显示,但是控件没有正确地呈现。自动完成停止工作,下拉框呈现为普通文本框,显示CountryID而不是Country名称。

enter image description here

我的视图代码:

@using (Html.BeginForm("Index", "CountryManagement", FormMethod.Post, new { id = "country-form" }))
{  
    @Html.ValidationSummary(true);
    <div id="form-content">
         @Html.Partial("_CountryForm", Model)
    </div>

}

在我的部分视图中的代码

<div class="form-group">
        @Html.Label("Search Country", htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-3">
            @(Html.Kendo().AutoCompleteFor(m => m.Search)
                          .DataTextField("Designation")
                          //.DataValueField("CountryID")
                          .Filter("contains")
                          .MinLength(2)
                          .DataSource(d => { d.Read(r => r.Action("SearchCountry", "Common")); })
                          .Events(e => e.Change("onChange")).Deferred()
            )
        </div>
    </div>

我的控制器中的代码

[HttpPost]
public PartialViewResult Edit(int id)
{
    //HTTP GET: api/Country/CountryDetails?id={id}&lang={lang}
    dynamic model =  //code to get selcted country data
    return PartialView("_CountryForm", model);
}

我的 .js 文件中的代码

function onChange() {
    
    if ($("#Search").data("handler")) {
        var data = $("#Search").data("handler").dataSource.data();
        var country = data.find(x => x.Designation == $("#Search").val());
        console.log("Country")
        if (country) {
            var request = $.post('/CountryManagement/Edit', { id: country.CountryID });
            request.success(function (data) {
                $("#form-content").html(data);
            });
        }
    }
}

页面加载时生成的HTML代码(仅限自动完成和下拉列表)。
<div class="form-group">
    <label class="control-label col-md-2" for="Search_Country">Search Country</label>
    <div class="col-md-3">
        <span tabindex="-1" role="presentation" class="k-widget k-autocomplete k-header k-state-default k-state-hover"><input data-val="true" data-val-length="Description  must have between 1  and 150 characters" data-val-length-max="150" data-val-length-min="1" id="Search" name="Search" type="text" data-role="autocomplete" class="k-input" autocomplete="off" role="textbox" aria-haspopup="true" aria-disabled="false" aria-readonly="false" aria-owns="Search_listbox" aria-autocomplete="list" has-focus="false" style="width: 100%;"><span class="k-icon k-loading" style="display:none"></span></span>
    </div>
</div>
<br>
<br>
<div class="form-group">
    <label class="control-label col-md-2" for="Country">Country</label>
    <div class="col-md-3">
       <span class="k-widget k-combobox k-header"><span tabindex="-1" unselectable="on" class="k-dropdown-wrap k-state-default"><input name="CountryID_input" class="k-input" type="text" autocomplete="off" title="" role="combobox" aria-expanded="false" tabindex="0" aria-disabled="false" aria-readonly="false" aria-autocomplete="list" aria-owns="CountryID_listbox" has-focus="false" style="width: 100%;"><span tabindex="-1" unselectable="on" class="k-select"><span unselectable="on" class="k-icon k-i-arrow-s" role="button" tabindex="-1" aria-controls="CountryID_listbox">select</span></span></span><input data-val="true" data-val-number="The field CountryID must be a number." id="CountryID" name="CountryID" type="text" value="0" data-role="combobox" aria-disabled="false" aria-readonly="false" has-focus="false" style="display: none;"></span>
        <span class="field-validation-valid text-danger" data-valmsg-for="CountryID" data-valmsg-replace="true"></span>
    </div>
</div>

局部视图重新加载后生成的HTML代码(仅包含自动完成和下拉菜单)

<div class="form-group">
    <label class="control-label col-md-2" for="Search_Country">Search Country</label>
    <div class="col-md-3">
        <input data-val="true" data-val-length="Description  must have between 1  and 150 characters" data-val-length-max="150" data-val-length-min="1" id="Search" name="Search" type="text" value="South Africa">
    </div>
</div>
<br>
<br>
<div class="form-group">
    <label class="control-label col-md-2" for="Country">Country</label>
    <div class="col-md-3">
       <input data-val="true" data-val-number="The field CountryID must be a number." id="CountryID" name="CountryID" type="text" value="1003">
        <span class="field-validation-valid text-danger" data-valmsg-for="CountryID" data-valmsg-replace="true"></span>
    </div>
</div>

我不确定这是否是ASP.Net MVC部分视图、Kendo控件或某些脚本在部分视图重新加载时应该重新运行的问题。有人可以帮忙吗?


你能展示一下调用你的 JS 代码的部分吗?(即在你的视图中的 JavaScript 部分?) - Raphaël Althaus
嗨@RaphaëlAlthaus,我已经添加了一些来自我的部分视图的代码。由于我的自动完成是一个Kendo-mvc控件,调用Javascript的部分是自动完成定义的一部分,并绑定到更改事件。== > .Events(e => e.Change("onChange")。谢谢。 - Ferox
你能展示一下在 Ajax 调用后生成的局部视图的 HTML 吗?可能会像这样:http://stackoverflow.com/questions/22412473/ajax-call-breaks-binding-to-object-children - Raphaël Althaus
谢谢提供链接,但这不是同一个问题。我的模型绑定完美无缺,并且我可以获取数据。然而,从你的最后一个请求中,我注意到服务器加载时生成的HTML代码与ajax重新加载时生成的代码确实不同。大部分差异似乎与一些缺失属性以及缺失的kendo样式有关。 - Ferox
你在浏览器控制台看到了任何错误吗? - Sunil Kumar
@SunilKumar 不,它不会在控制台上显示任何错误。 - Ferox
3个回答

3

在深入研究Telerik论坛并多次尝试失败后,我终于找到了问题所在。

部分视图中的Kendo小部件不应使用延迟初始化。

@(Html.Kendo().AutoCompleteFor(m => m.Search)
                      ///.. code removed to reduce complexity
                      .Events(e => e.Change("onChange")).Deferred()
 )

当视图通过服务器请求加载时,它会正确地呈现,因为在布局文件的末尾,所有使用@Html.Kendo().DeferredScripts()进行延迟初始化的小部件都被初始化。但是,当通过ajax重新加载部分视图时,延迟脚本初始化永远不会发生,因为这些脚本不会重新运行。
@Html.Kendo().DeferredScripts()添加到部分视图中可以解决ajax重新加载的问题,但在服务器加载时会成为一个问题:1- 延迟初始化将运行两次,2 - 因为kendo小部件具有jquery依赖项,并且会在包含jquery脚本之前运行。
我找到的解决方案是不要延迟小部件的初始化,但是这将使我们回到上面提到的jquery依赖性问题。尽管我尽力避免,但唯一真正有效的方法是在页面头部包含jquery。所有其他脚本(验证、kendo、自定义等)仍然位于底部,但主要的jquery脚本位于顶部。现在我的部分视图在服务器或ajax请求上完美加载。
总之:
  1. 不要在部分视图中使用延迟初始化
  2. 将jquery.min.js移到页面顶部。
希望有更好的方法,但现在它能解决问题。

1

检查页面脚本初始化错误!

我在这里遇到了同样的问题,花了3天时间解决它,我的问题最终是由于页面初始化脚本中缺少MutationObserver,在旧版safari浏览器中不可用。添加polyfill并修复init错误后,使用Kendo控件动态注入的ajax内容可以正常工作,无需延迟。希望这能为其他人节省一些挫败感。

此init错误影响了jquery的ready初始化器回调,对于Telerik依赖于它发出的每个控件的脚本块进行渲染。


这非常准确!修复我遇到的脚本错误解决了问题。谢谢。 - Dave

1

所以我在论坛上搜索了一下,也没有找到合适的解决方法。但我做了以下操作,看起来运行良好。基本上如果部分视图正常呈现,那么布局视图会处理延迟脚本,但如果请求是通过AJAX,则部分视图将继续呈现它们。

我把这个放在我的部分的底部:

@if (Context.Request.IsAjaxRequest())
{
    <div id="kendo-scripts">
        @Html.Kendo().DeferredScripts()
    </div>
}

FYI,留下你的kendo对象末尾的.Deferred(),以防这不明显。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接