我在击倒时遇到困难。从我的模型,我发送一个包含凭据列表的JSON对象。每个凭证都有一个" Id"," Name"和" Selected"属性。在我看来,我有2个列表。第一个显示所有凭据" Selected"值等于" false"。第二个列表显示所有具有" Selected"值等于" true"。
最初,所有项目都将包含" Selected"值等于false。当我双击列表中的项目时,"选择"值切换以便从第一个列表中删除它并添加第二个列表。我的问题是,我似乎无法使绑定正常工作。起初我能够正确填充第一个列表,我可以手动输入一个值(Id)到切换功能,这样在加载页面时,我指定的任何项目都在第二个列表中正确列出。但是,我这样做是错误的,因为我正在更改原始输入数据,而不是可观察数组,因此我的视图无法正确更新。
这就是我目前拥有它的方式。目前,当它进入toggleselected函数时,它不会检索正确的凭证(而在它使用原始的,不可观察的数据时它工作之前)。我肯定错过了什么!
MODEL(只是创建JSON的一种方法):
private void createJsonForAllCredentials()
{
List<CredentialLookupDto> credentials = proxy.Credential_RetrieveAll();
var optimizedCred = from c in credentials
select new
{
Name = c.Name,
Id = c.CredentialId,
Selected =
SelectedQualification != null && SelectedQualification.Credentials != null &&
SelectedQualification.Credentials.Any(p => p.CredentialId == c.CredentialId)
};
this.JsonAllCredentials = JsonConvert.SerializeObject(optimizedCred);
}
查看:
<div>
<table>
<tr>
<td class="fieldName_td">
@Html.Label("Available Credentials")
</td>
<td class="fieldData_td">
<select data-bind="foreach: $root.AllCredentials" multiple="multiple" name="ddallcredentials" id="allCredentials">
<!-- ko if: !Selected -->
<option data-bind="text:Name,value:Id"></option>
<!-- /ko -->
</select>
</td>
</tr>
</table>
</div>
<div>
<table>
<tr>
<td class="fieldName_td">
@Html.Label("Selected Credentials")
</td>
<td class="fieldData_td">
<select data-bind="foreach: $root.AllCredentials" multiple="multiple" name="ddSelectedCredentials" id="selectedCredentials">
<!-- ko if: Selected -->
<option data-bind="text:Name,value:Id"></option>
<!-- /ko -->
</select>
</td>
</tr>
</table>
</div>
}
@section scripts {
@Scripts.Render("~/Scripts/knockout-2.2.1.js", "~/jscripts/Administration/Interfaces/QualificationList.js", "~/Scripts/knockout.mapping-latest.js")
<script type="text/javascript">
$(function () {
TestNWJS.QualificationList.Init(@Html.Raw(Model.JsonAllCredentials));
})
</script>
}
视图模型:
///<reference path="~/Scripts/jquery-1.9.1.js" />
///<reference path="~/Scripts/knockout-2.2.1.js" />
///<reference path="~/Scripts/knockout.mapping-latest.js" />
var TestNWJS = TestNWJS || {};
TestNWJS.QualificationList = (function () {
//private functions
function CreateQualificationModel(allCredentialsList) {
TestNWJS.QualificationList.ViewModel = {};
TestNWJS.QualificationList.ViewModel.AllCredentials = ko.observableArray(allCredentialsList).extend({ notify: 'always' });
}
function toggleselected(array,id) {
var credential = ko.utils.arrayFirst(array, function (credential) {
var stringToInt = parseInt(id);
return credential.Id === stringToInt;
});
if (credential.Selected == false) {
credential.Selected = true;
}
else {
credential.Selected = false;
}
return credential;
}
//public function
return {
Init: function (allCredentialsList) {
CreateQualificationModel(allCredentialsList);
$("#allCredentials").live('dblclick', function (e) {
toggleselected(this.value);
});
$("#selectedCredentials").live('dblclick', function (e) {
toggleselected(this.value);
});
ko.applyBindings(TestNWJS.QualificationList.ViewModel);
}
}
})();
同样,只是为了澄清,初始列表正确加载。这个问题是当我想要双击一个项目以触发&#34;切换选择&#34;功能(双击触发器工作),该功能无法正常工作。它返回&#34;凭证&#34;的空值,这意味着我的ko.utils.arrayFirst实现不正确。还存在与绑定相关的其他问题。最后,当我传入原始数据时,我能够使一切正常工作&#34; allCredentialsList&#34;而不是&#34; TestNWJS.QualificationList.ViewModel.AllCredentials&#34;。我之所以这样做是因为&#34; TestNWJS.QualificationList.ViewModel.AllCredentials&#34;是可观察的,从而在属性发生变化时触发视图更新(在这种情况下,双击时为&#34; Selected&#34;属性)。
答案 0 :(得分:3)
我可能会错过一些东西,因为我现在没有时间完全测试它,但是,是的,你错过了一些东西。
您正在尝试使用live
函数中的jQuery通过DOM更新viewModel,从而绕过Knockout MVVM逻辑。
事实上,Knockout还有options
binding专门用于此类任务。
来自文档的改编示例:
<select data-bind="options: myOptionsList,
optionsText: 'countryName',
value: myValueBinding,
optionsCaption: 'Choose...'"></select>
如果您的viewmodel中有value
可观察对象,则myValueBinding
绑定会跟踪所选选项。
options
绑定在您的视图模型中为observableArray
,value
绑定将从该绑定更新。
arrayFirst
实用程序函数返回函数计算结果为true的第一个匹配项。在你的代码片段中,这是不可能的:在你的toggleSelected
函数中,你只传递一个数组而没有id,所以它永远不会评估为true(id = undefined)。
var credential = ko.utils.arrayFirst(array, function (credential) {
var stringToInt = parseInt(id);
return credential.Id === stringToInt;
});
不是将this.value
传递给toggleSelected(对Knockout没有意义,除非你打算使用DOM作为数据通信层而不是你的viewModel。所以你应该访问选项的绑定数据ko.dataFor()
,例如
$("#selectedCredentials").live('dblclick', function (e) {
var id = ko.dataFor(this).ID, array = ko.contextFor(this).$root.AllCredentials;
// if you have properly stored your arrays and properties, this will work:
toggleselected(array,id);
});
如果你在select
上绑定了这个,那就更容易了:
<select data-bind="event: { dblclick: toggleSelected }"></select>
您甚至不需要在视图中传递参数,因为event
和data
会自动作为参数传递。在您的toggleSelected
功能中,您有:
TestNWJS.QualificationList.ViewModel.toggleSelected = function(data, e) {
var id = data.ID, array = TestNWJS.QualificationList.ViewModel.AllCredentials;
// if you have properly stored your arrays and properties, this will work:
toggleselected(array,id);
});