0

我在模式对话框上有一个选择元素和一个文本输入元素。我想从选择输入中选择一个选项并使用该值来预填充文本输入元素(这只是帮助用户使用预填充的名称,然后允许用户根据需要覆盖该名称)。

我有一个车库里的汽车清单,它们都有一个型号和一个名字。

var carTypes = [{"id":1,"name":"Audi"}, {"id":2,"name":"BMW"}, {"id":3,"name":"Mercedes"}];

var Car = function() {
    var self = this;
    self.typeId = ko.observable();
    self.name = ko.observable();
    self.typeName = ko.computed(function() {
        var nam =  $.grep(carTypes, function(item) { return item.id == self.typeId(); });
        return name;
    };
}

var ViewModel = function() {
    var self = this;
    self.carTypes = carTypes;
    self.selectedCar = ko.observable();
    self.saveCar = function() {
        // push the data from selectedCar to self.cars array
        // close the dialog
    };
    self.editCar = function(item, event) { 
        self.selectedCar(item);
        // display the dialog
    };
    self.cars = ko.observableArray([]);
}

ko.bindingHandlers.initialName = {
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        bindingContext.$data.name(value);
    }
};

ko.applyBindings(new ViewModel());


<div data-bind="foreach: cars">
    <div data-bind="click: editCar">
        <div>Type: <div data-bind="text: typeName"/></div>
        <div>Name: <div data-bind="text: name" /></div>
    </div>
</div>

<div id="carDialog">
    <div data-bind="with: selectedCar">
        <select data=bind="options: $root.carTypes, optionsText: 'name', optionsValue: 'id', value: typeId", optionsCaption: 'Pick a car type'></select>
        <input data-bind="value: name", initialName: carTypeName"/>
    </div>
</div>

我编写了一个自定义绑定处理程序来帮助我,但不确定我是否做得对,或者我是否可以使用订阅来实现类似的功能typeId

如果我有一辆车保存了以下数据:

{ typeId: 2, name: 'My new BMW'}

问题是当我选择此项目进行编辑时,名称总是显示“宝马”,而不是“我的新宝马”

这个明显简单的问题成为m'colleagues 的笑柄,他们指责我选择淘汰赛,理由是它在jQuery 中会多么简单。

如果代码不完整但我的实际实现稍大但我希望我提供了足够的相关代码来解释问题,请提前提供任何帮助和 apols 谢谢

4

1 回答 1

1

虽然这是可能的,但您将很难为此创建绑定处理程序,因为这些处理程序旨在处理与一个(部分)视图模型和一部分 DOM 的交互。

你所拥有的是两个 ViewModel 之间的依赖关系。使用 MVVM,弄清楚如何正确地做到这一点,并让 mvvm-framework 处理 DOM 更新。

订阅或等效的可写计算将能够做到这一点。一旦select更改并因此更新 VM 属性,您就可以设置默认名称。

例如:

var Car = function(carType) {
    var self = this,
        _type = ko.observable();;
  
    self.name = ko.observable("");
  
    self.type = ko.computed({
        read: _type,
        write: function(newValue) {
            var oldDefaultName = !!_type() ? "My new " + _type().name : "";
            var newDefaultName = !!newValue ? "My new " + newValue.name : "";
          
            if (self.name() === oldDefaultName) {
                self.name(newDefaultName);
            }
            
            _type(newValue);
        }
    });
  
    self.type();
}

var ViewModel = function() {
    var self = this;
  
    self.carTypes = [{"id":1,"name":"Audi"}, {"id":2,"name":"BMW"}, {"id":3,"name":"Mercedes"}];
    
    self.newCar = ko.observable(new Car(self.carTypes[0]));  
}

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<div id="carDialog">
    <div data-bind="with: newCar">
        <select data-bind="options: $root.carTypes, optionsText: 'name', value: type, optionsCaption: 'Pick a car type'"></select>
        <input data-bind="value: name"/>
    </div>
</div>

因为您的示例代码无法运行(它有语法错误,一些缺失的部分,以及我没有看到它工作就无法理解的东西),我不得不做出一些假设并以不同的方式做一些事情。

如果您必须使用绑定处理程序,则需要从上面计算的逻辑中获取逻辑并将其应用于 bindingContext 的适当部分。

于 2015-09-17T07:31:50.297 回答