【问题标题】:Knockout only works first time淘汰赛只适用于第一次
【发布时间】:2014-02-24 11:03:31
【问题描述】:

我在淘汰赛方面遇到了一些麻烦,希望这里有人能提供帮助。

我有两个 jQuery 函数。一个,使用敲除,绑定到页面上的单个元素。另一个绑定到其余元素,然后调用第一个函数。

数据取自返回 Json 的 AJAX 请求。

我遇到的问题是与 pGroups 列表有关。它第一次运行良好,但是当您再次单击时它会失败并且需要刷新才能再次运行。

控制台错误是:NotFoundError: Node was not found

编辑:更新代码以显示进度

jQuery 是:

//Load user data into the action window when a user is selected
$('.ListUserLink').click(function () {

    var url = '@Url.Action("DisplayUser", "AjaxUser")' + '?UserId=' + $(this).attr("UserId") + '&UserNum=' + $(this).attr("UserNum") + "&SectId=" + $(this).attr("Sect");

    $.ajax({
        url: url,
        contentType: "application/json; charset=utf-8",
        type: 'POST',
        context: this,
        timeout: 60000,
        dataType: 'json',
        tryCount: 0,
        retryLimit: 3,
        success: function (data) {
            //ko.applyBindings(new UserViewModel(data));
            viewModel.user = new userModel(data);
        },
        error: function (httpRequest, textStatus, errorThrown) {
            alert("Error");
        }
    });
});

//Load sections on department index change
$("#ddbDepartments").change(function () {
    var url = '@Url.Action("GetSectionsByDept", "AjaxUser")' + '?deptId=' + $(this).val();
    $.ajax({
        url: url,
        contentType: "application/json; charset=utf-8",
        type: 'POST',
        context: this,
        timeout: 60000,
        dataType: 'json',
        tryCount: 0,
        retryLimit: 3,
        success: function (data) {
            //ko.applyBindings(new SectionViewModel(data), $(".SectionsDDB")[0]);
            viewModel.sections = new userModel(data);
        },
        error: function (httpRequest, textStatus, errorThrown) {
            alert("Error");
        }
    });
});



//Assign Section details to fields
function sectionsModel(data) {
    this.sectionList = ko.observableArray(data.SectionList);
//      this.sections = this.sectionList;
//      this.selectedItem = parseInt($("#OldSectionId").value);
};

//Assign user details to fields
function userModel(data) {

    this.fullName = ko.observable(data.FirstName + " " + data.Surname);

    this.firstName = ko.observable(data.FirstName);
    this.surname = ko.observable(data.Surname);
    this.usernum = ko.observable(data.UserNum);

    //Assign JobTitle Dropdown and selected value
    this.jobTitlesList = ko.observableArray(data.TitlesList);
    this.jobTitles = this.jobTitlesList;
    this.selectedItem = data.JobTitleNum;

    //Assign Group/Application list
    this.pGroups = ko.observableArray(data.GroupList);

    this.sections = ko.observableArray([{}]);

    this.ext = ko.observable(data.Ext);
    this.userId = ko.observable(data.UserId);
    this.olduserid = ko.observable(data.UserId);
    $("#ddbDepartments").val(data.DeptId);
    this.oldsectionid = ko.observable(data.SectionId);
    $("#ddbDepartments").change();
    this.oldsectionid = ko.observable(data.SectionId);
    //$("#SectionsDDB").val(data.SectionId);
};

var wrapper = function () {
    this.user = new userModel(userdata);
    this.sections = new sectionsModel(sectiondata);
};

var viewModel = new wrapper();
    ko.applyBindings(viewModel);

第二次尝试失败的 pGroups HTML 是:

 <div data-bind="with: user" id="ActionWindow">

<form action="@Url.Action("SaveUserDetails", "AJAXUser")" method="post" class="AjaxSubmit" id="userDetailsForm">
    <h2>User: <span data-bind="text: fullName"></span></h2>
    <table>
        <tr>
            <td>First Name:</td>
            <td><input  type="text" name="FirstName" id="FirstName" data-bind="value: firstName" /></td>
            <td>
                <input type="hidden" name="UserNum" id="UserNum" data-bind="value: usernum" />
                <input type="hidden" name="OldUserId" id="OldUserId" data-bind="value: olduserid" />
                <input type="hidden" name="OldSectionId" id="OldSectionId" data-bind="value: oldsectionid" />
            </td>
            <td></td>
        </tr>

        <tr>
            <td>Surname:</td>
            <td><input type="text" name="Surname" id="Surname" data-bind="value: surname" /></td>
            <td></td>
            <td></td>
        </tr>

        <tr>
            <td>Job Title:</td>
            <td><select name="JobTitleNum" id="TitlesList" data-bind="options: jobTitles, optionsValue: 'TitleId', optionsText: 'Title', value: selectedItem"></select></td>
            <td></td>
            <td></td>
        </tr>

        <tr>
            <td>Extension:</td>
            <td><input type="text" name="Ext" id="Ext" data-bind="value: ext" /></td>
            <td></td>
            <td></td>
        </tr>

        <tr>
            <td>Login ID:</td>
            <td><input type="text" name="UserId" id="UserId" data-bind="value: userId" /></td>
            <td></td>
            <td></td>
        </tr>

        <tr>
            <td>Department:</td>
            <td>
                <select id="ddbDepartments" name="DeptId">
                    @foreach (var d in Model.DepartmentList)
                    {
                        <option value="@d.DeptId">@d.DeptName</option>
                    }
                </select>
            </td>
            <td>Section: </td>
            <td>
                <select name="SectionId" class="SectionsDDB" data-bind="options: $root.sections.list, optionsValue: 'SectId', optionsText: 'SectName', value: SectionId"></select>
                @*<select name="SectionId" class="SectionsDDB" data-bind="options: sections, optionsValue: 'SectId', optionsText: 'SectName', value: selectedItem"></select>*@
            </td>
        </tr>
    </table>
    <input type="submit" value="Update User" />
    <br />
</form>

<h2>Current Groups</h2>
<table>
    <tbody data-bind="foreach: pGroups">
        <tr>
            <td data-bind="text:AppName"></td>
            <td data-bind="text:GroupName"></td>
        </tr>
    </tbody>
</table>

其他一切正常。

我确实找到了这个:http://knockoutjs.com/documentation/plugins-mapping.html

这表明我应该像这样映射:

var viewModel = ko.mapping.fromJS(data, mapping);

但尽我所能,我无法弄清楚如何将它应用到我的代码中。

任何帮助都将不胜感激。

【问题讨论】:

  • 不要每次换部门都调用ko.applyBindings函数。每次调用 ko.applyBindings 时,都会检查整个 DOM 是否存在绑定。因此,如果您多次执行此操作,您将获得同一元素的多个绑定。请检查此链接以确保您了解如何在同一页面上拥有多个视图:stackoverflow.com/questions/8676988/…
  • 请添加一个 jsfiddle 以防您无法解决问题
  • 所以我需要从 AJAX 成功中删除 ko.apply 绑定并将其映射到那里?您链接中的示例似乎是针对 Dom 的单独部分的单个调用,因为我有一些重叠。这是一个 jsFiddle,但我一辈子都无法让它工作jsfiddle.net/dariune/8djDw
  • 你应该替换 viewModel.sections = new userModel(data); with viewModel.sections = new sectionModel(data);

标签: jquery ajax asp.net-mvc knockout.js


【解决方案1】:

根据我在上一条评论中提供的链接 (http://www.knockmeout.net/2012/05/quick-tip-skip-binding.html) 我做了一个你可能的视图模型的例子:

//the overall model
var wrapper = function () {
    this.user = ko.observable();
    this.user(new userModel(userdata));
    this.sections = new sectionsModel(sectiondata);
};
var viewModel = new wrapper();
ko.applyBindings(viewModel);

然后在成功$('.ListUserLink').click就可以有:

viewModel.user(new UserViewModel(data));

并且在 $("#ddbDepartments").change 的成功中你可以拥有:

viewModel.sections.sectionList(data.SectionList);

在视图中,您可以使用 with 绑定和 $root 来绑定嵌套的视图模型:

  <div data-bind="with: user">
        <h2>User: <span data-bind="text: fullName"></span></h2>
        ...
      <select name="SectionId" class="SectionsDDB" data-bind="options: $root.sections.sectionList, optionsValue: 'SectId', optionsText: 'SectName', value: $root.sections.selectedValue"></select>
        ...
    </div>

【讨论】:

  • 谢谢我已经按照链接所说的做了,我想我快到了,这次我错过了一些愚蠢的东西。我得到错误:无法解析绑定。全名(我想象其余的)。我已经更新了我的 jsfiddle 来展示这个:jsfiddle.net/dariune/8djDw/2
  • 我做了更改:jsfiddle.net/8djDw/5。我还添加了 jquery 库以设置 ddbDepartments 的值并将 SectionId 属性添加到 userModel
  • 如果你想让选中的部分作为sectionsModel的一个属性,你可以使用一个变量来设置它的初始值,并在sectionsModel中声明selectedValue observable:jsfiddle.net/8djDw/6。如果您需要任何进一步的帮助,请告诉我。
  • 我真的很挣扎,对不起。似乎加载了两次 AJAx 请求部分。我已经更新了原始请求中的代码,以更好地显示我的位置。我非常感谢您为此付出的所有努力。
  • 好的,我已经完成了,我已经将包装器和 viewModel 放在了脚本的顶部。它说 userData 没有定义(因为在我的脚本中没有 userData 变量它只使用来自 AJAX 请求的数据。所以我需要防止它在调用 AJAX 请求之前更新页面(WHich 是点击或更改。
【解决方案2】:

据我了解,这些部分是根据部门选择加载的。那么为什么不直接将 sectionList observableArray 添加到 UserViewModel 并添加对部门 id 的订阅,这样每次部门更改时,都会加载部门列表:

this.DeptId = ko.observable(data.DeptId);
this.sectionList = ko.observableArray(GetSections(this.DeptId()));
this.DeptId.subscribe(function () {
              var newSections =  GetSections(this.DeptId());
              this.sectionList(newSections);
            }, this);

GetSections 函数应该调用您的 GetSectionsByDept 方法。 在您的 jsfiddle 中,如果您注释以下行,数据将加载:

$("#ddbDepartments").val(data.DeptId);
$("#ddbDepartments").change();
$("#SectionsDDB").val(data.SectionId);

您还应该将下拉列表部门替换为:

<select name="DeptId" id="ddbDepartments" data-bind="options: DepartmentList, optionsValue: 'Id', optionsText: 'DeptName', value: DeptId"></select>

但请确保有一组具有 Id/DeptName 属性的部门对象。

【讨论】:

  • 您好,感谢您的回复。 ddbdepartments 在页面加载时加载,数据来自控制器。所以它需要在它当前所在的 foreach 中。是的,你大部分是正确的。单击一个按钮(其中有很多)将调用 ListUserLink AJAX 方法,该方法然后调用 UserViewModel,一旦选择了部门值,它将调用 SectionViewModel 来显示部分。完成后,您可以选择一个只调用 SectionViewModel 的部门。所以我将它们分开,因为 ListUserLink 数据不包含部分信息。这有意义吗?
  • 是的,但是你仍然会有重叠的绑定,因为当你调用 ko.applyBindings(new UserViewModel(userdata));它也适用于 SectionsDDB。请查看此链接以了解处理方法:knockmeout.net/2012/05/quick-tip-skip-binding.html.
【解决方案3】:

你不需要实例一个新的 ViewModel 总是你有 ajax 服务器响应。 您可以在页面准备就绪时应用绑定并在 ajax 完成时更新数据更改,或者您可以删除视图模型绑定并在您的 ajax 中再次应用。

【讨论】:

  • 感谢您的回复。如果没有新的视图模型,我该怎么做?
  • 在你的 change 事件成功时,替换 "ko.applyBindings(new SectionViewModel(data), $(".SectionsDDB")[0]);"到“yourViewModelInstance.secionList(data.SectionList);”
  • 不应该先声明viewModel吗?我已经尝试了您所说的更改为 SectionViewModel.sectionList(data.SectionList);但这没有用。说 SectionViewModel.sectionList 不是我所期望的函数,因为它没有声明一个新实例。
  • @LexEichner,在您的文档就绪事件中声明您的视图模型。示例: var yourInstance = new SectionViewModel();并且你的 ajax 成功你需要告诉你的 viewmodelInstace 来更新它的 SectionList。示例:yourInstance.sectionList(data.SectionList);当您使用此代码行时,您的视图将自动更新 sectionList
  • 我喜欢这个想法,但它仍然说 yourInstance 没有定义。明天我会继续努力。
猜你喜欢
  • 2018-03-25
  • 2012-05-01
  • 2013-05-17
  • 2014-08-05
  • 2013-03-30
  • 2013-01-13
  • 2012-08-25
  • 2020-06-22
  • 2015-01-18
相关资源
最近更新 更多