敲除数组和绑定问题 [英] Knockout array and binding issues

查看:50
本文介绍了敲除数组和绑定问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在淘汰赛上遇到困难.从我的模型中,我正在发送一个包含凭据列表的JSON对象.每个凭证都有一个"Id","Name"和"Selected"属性.我认为,我有2个列表.第一个显示所有"Selected"值等于"false"的凭证.第二个列表显示选择"值等于真"的所有项目.

I am having difficulties with knockout. From my model, I am sending in a JSON object that contains a list of credentials. Each credential has a "Id", "Name", and "Selected" property. In my view, I have 2 lists. The first shows all credentials with "Selected" value equal to "false". The second list shows all items that have "Selected" value equal to "true".

最初,所有项目的已选择"值都将等于false.当我双击列表中的项目时,已选择"值将切换,以便将其从第一个列表中删除并添加第二个.我的问题是我似乎无法使绑定正常工作.最初,我能够正确填充第一个列表,并且可以为切换功能手动输入一个值(Id),这样,在加载页面时,我指定的任何项目都会在第二个列表中正确列出.但是,我做错了,因为我更改了原始输入数据,而不是可观察的数组,因此我的视图无法正确更新.

Initially, all the items will have "Selected" value equal to false. When I double click the item in the list, the "Selected" value toggles so that it is removed from the first list and added the the second. My issue is that I can't seem to get the binding to work correctly. At first I was able to get the first list to populate correctly and I could manually enter in a value (Id) to the toggle function so that upon loading the page, whatever item I specified was listed properly on the second list. However, I was doing this incorrectly because I was changing the raw input data, not an observable array so my view wouldn't update correctly.

这就是我目前的情况.截至目前,当它进入toggleselected函数时,它并没有检索正确的凭据(而在使用原始的不可观察的数据之前,它才起作用).我肯定会丢失一些东西!

This is how I currently have it. As of right now when it goes into the toggleselected function, it isn't retrieving the correct credential (whereas before it was working when I used the raw, non observable data). I'm definitely missing something!

MODEL(只是创建JSON的一种方法):

MODEL (just the one method that creates the 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>

}

VIEWMODEL:

VIEWMODEL:

///<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);
    }
}

})();

再次,为了澄清起见,初始列表正确加载.此问题是当我想双击一个项目来触发"toggleselected"功能(双击触发器起作用)时,该功能无法正常工作.它为凭据"返回一个空值,因此这意味着我的ko.utils.arrayFirst实现不正确.也可能存在与绑定有关的其他问题.最后,当我传入原始数据"allCredentialsList"而不是"TestNWJS.QualificationList.ViewModel.AllCredentials"时,我能够使一切正常工作.我这样做的原因是因为可以观察到"TestNWJS.QualificationList.ViewModel.AllCredentials",从而在属性更改时触发视图更新(在这种情况下,双击属性为"Selected").

Again, just for clarification, the initial list loads correctly. This issue is when I want to double click an item to trigger the "toggleselected" function (the double click trigger works), the function does not work correctly. It returns a null value for "credential", thus meaning that my ko.utils.arrayFirst implementation isn't correct. There are potentially other issues related to binding as well. And finally, I was able to get everything to work correctly when I passed in the raw data "allCredentialsList" instead of "TestNWJS.QualificationList.ViewModel.AllCredentials". The reason I am doing so is because "TestNWJS.QualificationList.ViewModel.AllCredentials" is observable thus triggering a view update when a property changes (in this case the "Selected" property upon a double click).

推荐答案

我可能会错过一些内容,因为我现在没有时间对其进行完整的测试,但是是的,您缺少了一些内容. 您正在尝试使用live函数中的jQuery通过DOM更新viewModel,从而绕过了Knockout MVVM逻辑.

I might miss something as I've no time right now to test it completely, but yes you're missing something. You're trying to update your viewModel through the DOM with jQuery in the live functions, thus bypassing the Knockout MVVM logic.

实际上,淘汰赛还具有专门为此目的设计的 options绑定那种任务. 来自文档的改编示例:

In fact Knockout also has an options binding which is designed specifically for this kind of task. Adapted example from the docs:

<select data-bind="options: myOptionsList,
                       optionsText: 'countryName',
                       value: myValueBinding,
                       optionsCaption: 'Choose...'"></select>

如果在视图模型中有可观察的myValueBinding,则value绑定会跟踪所选选项.
options绑定是视图模型中的observableArray,将从中更新value绑定.

The value binding keeps track of the selected option if you have a myValueBinding observable in your viewmodel.
The options binding is an observableArray in your view model, from which the value binding will be updated.

arrayFirst实用程序函数返回该函数评估为true的第一个匹配项.在您的代码段中这是不可能的:在您的toggleSelected函数中,您仅传递一个数组且没有id,因此它永远不会求值为true(id =未定义).

The arrayFirst utility function returns the first match for which the function evaluates true. In your snippet this is impossible: in your toggleSelected functions you only pass an array and no id, so it will never evaluate to true (id = undefined).

   var credential = ko.utils.arrayFirst(array, function (credential) {
        var stringToInt = parseInt(id);
        return credential.Id === stringToInt;
    });

使用而不是绕过Knockout(事件处理)

与其将this.value传递给toggleSelected(对于Knockout毫无意义,除非您打算将DOM用作数据通信层而不是viewModel.所以应该使用ko.dataFor()访问该选项的绑定数据,例如

Using instead of bypassing Knockout (event handling)

Instead of passing this.value to toggleSelected (which has no meaning for Knockout, unless you intend to use the DOM as data communication layer instead of your viewModel. So you should access the option's bound data with ko.dataFor(), eg

$("#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上,那会更加容易:

If you bound this live on your select it would have been even easier:

<select data-bind="event: { dblclick: toggleSelected }"></select>

您甚至不需要在视图中传递参数,因为eventdata会自动作为参数传递.在您的toggleSelected函数中,您将拥有:

You don't even need to pass parameters in the view, because event and data are automatically passed as parameter. In your toggleSelected function you'd have:

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);
});

这篇关于敲除数组和绑定问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆