使用下拉列表进行敲除绑定以预填充文本框

时间:2015-09-17 06:04:53

标签: javascript knockout.js bindinghandlers

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

我的车库中有车辆列表,它们都有型号和名称。

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'}

问题是,当我选择要编辑的项目时,名称始终显示“宝马”,而不是“我的新宝马”

这个明显的简单问题对于那些同意我的选择淘汰赛的同事来说是一个笑柄,引用了jQuery的简单性。

如果代码不满但预先提出任何帮助并提前解决,但我的实际实现略大但我希望我提供了足够的相关代码来解释问题 感谢

1 个答案:

答案 0 :(得分:1)

尽管可能,但您在创建绑定处理程序方面遇到了麻烦,因为这些是为了处理与一个(部分)视图模型的交互而一个DOM的一部分。

你有两个ViewModel之间的依赖关系。使用MVVM,弄清楚如何正确地执行 ,并让mvvm-framework处理DOM更新。

订阅或等效的可写计算将能够执行此操作。更改select并更新VM属性后,您可以设置默认名称。

例如:

&#13;
&#13;
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());
&#13;
<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>
&#13;
&#13;
&#13;

因为你的示例代码不可运行(它有语法错误,一些缺失的部分,以及我在没有看到它的情况下无法理解的事情),我不得不做出一些假设并做一些不同的事情。

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