如何确定哪个DOM元素与Knockout可观察数组元素相对应?

时间:2014-09-16 16:40:50

标签: javascript jquery html knockout.js knockout-subscribe

在我的模型中,我有一个带有可观察元素的对象数组。我订阅了其中一个元素(下拉列表)以填写下一个下拉列表(级联下拉列表)。我现在需要在这些下拉列表中获取所选值的描述。我如何从下拉列表中提取该值?我试图避免在可能的情况下对服务器运行查询。

过去我已经完成了self.deptName($('#AssignedDepartment option:selected').text());,但现在这个下拉列表并不是唯一的。我可以有很多选择。我在每个字段上使用uniqueName: true。如何在订阅中确定哪个下拉列表发生了变化?

以下是我订阅的内容:

    // Build the hours types when the request type is selected
    self.RequestType.subscribe(function (newValue) {
        FindRequestType(newValue, function (record) {
            // Do stuff
        });
    });

以下是下拉列表的HTML:

<select class="required span12" data-bind="leaveTypeDropDown: RequestType, uniqueName: true"></select>

这是bindingHandler:

ko.bindingHandlers.leaveTypeDropDown = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        // If we don't have the leave request dropdown data, pull it.
        if (jsonRequestType === "") {
            $.ajax({
                'async': false,
                'url': '/api/payroll/LeaveRequestTypes/',
                'dataType': 'text json',
                'type': 'GET',
                'success': function (json) {
                    jsonRequestType = json;
                    jsonRequestTypeRecieved = true;
                }
            });
        }

        // Fill the drop down list.
        LoadRequestType(element);

        // register event handler where bound observable will be changed
        ko.utils.registerEventHandler(element, 'change', function () {
            var observable = valueAccessor();
            observable(element.value);
        });

        // Select the value from the previous record if there is one.
        if (selectedRequestType !== null) {
            element.value = selectedRequestType;
            ko.utils.triggerEvent(element, 'change');
            selectedRequestType = null;
        }
    }
};

更新1:由于存在混淆。如果我在下拉列表中选择“假期”文本的值“VAC”。如何将“假期”文本添加到我的模型中?

更新2:这是一个jsFiddle,上面列出了我的(大多数)工作代码。 http://jsfiddle.net/MikeWills/cykuqxto/6/出于某种原因,在加载时,我的下拉不起作用,但是再添加一天,你会看到我的工作下拉列表。

1 个答案:

答案 0 :(得分:1)

我们必须稍微清理你的方法。首先,让我们在您的模型上创建我们需要的所有可观察对象,并使用您的ajax调用填充第一个下拉选项:

var viewModel = {
    firstDropDownOptions: ko.observableArray(),
    firstDropDownChoice: ko.observable()
};

$.ajax(...).done(function (data) {
    // process data and assign
    // for the binding below to work, processedData has to have items like this:
    // {textProperty: 'some text', otherProperty: ...}
    // as you said in a comment, you have option groups so I'm going to assume
    // processedData looks like this overall:
    // [{group: 'one', options: [{text: 'Vacation', value: 'VAC'}, ...]}, ...]
    viewModel.firstDropDownOptions(processedData);
});

然后让我们使用options binding

将该observable绑定到您的下拉菜单
<select data-bind="foreach: firstDropDownOptions, value: firstDropDownChoice">
    <optgroup data-bind="attr: {label: label}, foreach: options">
        <option data-bind="text: text, option: $data"></option>
    </optgroup>
</select>

这是使用KnockoutJS - Binding value of select with optgroup and javascript objects的自定义绑定:

ko.bindingHandlers.option = {
    update: function(element, valueAccessor) {
       var value = ko.utils.unwrapObservable(valueAccessor());
       ko.selectExtensions.writeValue(element, value); // note this is magic
    }        
};

最后,让我们订阅监视第一个下拉列表更改的observable:

viewModel.firstDropDownChoice.subscribe(function (newChoice) {
    // in this function, newChoice is the option selected in the first drop down,
    // but not just the value, the whole object, so you can do:
    console.log(newChoice, newChoice.text);
});