knockout -jqAutocomplete`options.value不是函数`错误

时间:2017-08-17 16:47:19

标签: javascript jquery jquery-ui knockout.js knockout-3.0

我正在尝试使用https://github.com/rniemeyer/knockout-jqAutocomplete将淘宝购物卡转换为jquery自动完成功能。

下拉列表有效,无论选择该值后,我都会得到:Uncaught TypeError: options.value is not a function

我的绑定是:

<tbody data-bind="foreach: lines">
  <tr>
    <td>
        <input data-bind="jqAuto: { source: $root.productData, labelProp: 'sku', value: $parent.product }" />
    </td>
    <td>
        <input data-bind="jqAuto: { source: $root.productData, labelProp: 'name', value: $parent.product }"/>
    </td>
    <td class="quantity">
        <input data-bind='visible: product, value: quantity, valueUpdate: "afterkeydown"'/>
    </td>
    <td class="price">
        <span data-bind="visible: product, value: price"> </span>
    </td>
    <td class="subTotal">
        <span data-bind="visible: product, value: subtotal"> </span>
    </td>
    <td>
        <a href="#" data-bind="click: $parent.removeLine">Remove</a>
    </td>
  </tr>
</tbody>

我的观点模型是:

var QuoteLine = function() {
    var self = this;
    self.product = ko.observable();
    self.price = ko.observable();
    self.quantity = ko.observable(1);
    self.subtotal = ko.computed(function() {
        return self.product() ? self.price() * parseInt("0" + self.quantity(), 10) : 0;
    });
};

var Quote = function() {
    // Stores an array of lines, and from these, can work out the grandTotal
    var self = this;
    self.lines = ko.observableArray([new QuoteLine()]); // Put one line in by default
    self.grandTotal = ko.computed(function() {
        var total = 0;
        $.each(self.lines(), function() { total += this.subtotal() });
        return total;
    });

    self.productBeingEdited = ko.observable();

    self.editProduct = function(line) {
        console.log("self.editProduct " + line.quantity());
        self.productBeingEdited(line);
    };

    self.saveProduct = function(vm) {
        console.log("save");
    };

    self.productData = [
        {
            "man": "avaya",
            "sku" : "323",
            "name" : "1608-I Handset",
            "description": "An Avaya handset for IP Office and Aura systems."
        },
        {
            "man": "avaya",
            "sku": "324",
            "name": "1616-I Handset",
            "description": "An Avaya handset for IP Office and Aura systems."
        },
        {
            "man": "cisco",
            "sku" : "50ab",
            "name": "Cicso SIP handset",
            "description": "A Cisco handset."
        }
    ];

    self.addLine = function () { self.lines.push(new QuoteLine()) };

    self.removeLine = function(line) { self.lines.remove(line) };

    self.save = function () { /* snip */ };
};


ko.applyBindings(new Quote());

请问:

  1. 我想要的是摆脱错误!
  2. 对于sku字段,似乎提取搜索名称,并且sku的名称字段,即50a字段中的name会显示思科。如何将其锁定到仅适用于该列的标签?
  3. 如何设置Name字段取决于Sku字段(反之亦然),允许我通过Sku或Name查找并确保正确的product() observable得到更新?
  4. 我的小提琴就在这里:http://jsfiddle.net/m429944x/10/

1 个答案:

答案 0 :(得分:1)

尝试更改值:$ parent.product to product

http://jsfiddle.net/m429944x/11/

HTML:

<tbody data-bind="foreach: lines">
  <tr>
    <td>
        <input data-bind="jqAuto: { source: $root.productData, labelProp: 'sku', value: product }" />
    </td>
    <td>
        <input data-bind="jqAuto: { source: $root.productData, labelProp: 'name', value: product}"/>
    </td>
    <td class="quantity">
        <input data-bind='visible: product, value: quantity, valueUpdate: "afterkeydown"'/>
    </td>
    <td class="price">
        <span data-bind="visible: product, value: price"> </span>
    </td>
    <td class="subTotal">
        <span data-bind="visible: product, value: subtotal"> </span>
    </td>
    <td>
        <a href="#" data-bind="click: $parent.removeLine">Remove</a>
    </td>
  </tr>
</tbody>

使用Javascript:

var QuoteLine = function() {
    var self = this;
    self.product = ko.observable();
    self.price = ko.observable();
    self.quantity = ko.observable(1);
    self.subtotal = ko.computed(function() {
        return self.product() ? self.price() * parseInt("0" + self.quantity(), 10) : 0;
    });
};

var Quote = function() {
    // Stores an array of lines, and from these, can work out the grandTotal
    var self = this;
    self.lines = ko.observableArray([new QuoteLine()]); // Put one line in by default
    self.grandTotal = ko.computed(function() {
        var total = 0;
        $.each(self.lines(), function() { total += this.subtotal() });
        return total;
    });

    self.saveProduct = function(vm) {
        console.log("save");
    };

    // Operations
    self.addLine = function () { self.lines.push(new QuoteLine()) };

    self.removeLine = function(line) { self.lines.remove(line) };

    self.save = function () {
        var dataToSave = $.map(self.lines(),
            function(line) {
                return line.product()
                    ? {
                        productName: line.product().name,
                        quantity: line.quantity()
                    }
                    : undefined
            });
        alert("Could now send this to server: " + JSON.stringify(dataToSave));
    };

    self.productData = [
        {
            "man": "avaya",
            "sku" : "323",
            "name" : "1608-I Handset",
            "description": "An Avaya handset for IP Office and Aura systems."
        },
        {
            "man": "avaya",
            "sku": "324",
            "name": "1616-I Handset",
            "description": "An Avaya handset for IP Office and Aura systems."
        },
        {
            "man": "cisco",
            "sku" : "50ab",
            "name": "Cicso SIP handset",
            "description": "A Cisco handset."
        }
    ];
};

ko.applyBindings(new Quote());