【问题标题】:knockout binding using a dropdown to prepopulate a textbox使用下拉列表预填充文本框的淘汰赛绑定
【发布时间】:2015-09-17 06:04:52
【问题描述】:

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

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

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'同事的笑柄,他们斥责我选择淘汰赛,理由是它在jQuery中会多么简单。

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

【问题讨论】:

  • 你能在 JSFiddle 中创建一个小型的工作复制品吗?您当前的代码示例充满了小错别字和语法错误。我试图想出一个:jsfiddle.net/kfc3grp6,除了这个小错误之外,您的代码似乎可以工作......
  • 道歉 nemesv(并保证你不会笑)但我的公司阻止访问 jsfiddle :-|
  • 小错字@nemesv fiddle in view 使用initialName:typeName,而不是使用不存在的carTypeName,而alan as nemsev 提到您的代码没有问题。
  • 在问题和答案中不需要 jsfiddles,您可以使用 Stack Snippets(例如我对这样一个 sn-p 的回答)。 @nemesv 的底线仍然存在:确保您发布的代码是实际的复制品(或至少在发布之前修复语法错误)。

标签: javascript knockout.js bindinghandlers


【解决方案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 的适当部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-14
    • 2016-05-27
    • 2015-06-11
    • 1970-01-01
    • 2014-06-07
    • 2012-11-29
    • 1970-01-01
    相关资源
    最近更新 更多