1

I am trying to access a property of an object, I know the object exists (and has the property I need) as i can log it to the console.

However when i try and access it, it says Cannot read property 'price' of null.

I am a C# developer and little confused I must be doing something wrong but i do not know what? From my screenshot, you can see the object returned.

My code is below:

self.total = ko.computed(function(){
    var total = 0;      
    var selectedServerName = this.selectedServer();
    var selectedServerObject = ko.utils.arrayFirst(this.server, function(server){
        console.log("server.name = " + server.name);
        console.log("selectedServerName = " + selectedServerName);
        var serverCompare = (server.name == this.selectedServer());
        console.log("serverCompare is " + serverCompare);
    }, this);

    var selectedOsName = this.selectedOs();
    var selectedOsObject = ko.utils.arrayFirst(this.os, function(os){
        console.log("os.name = " + os.name);
        console.log("selectedOsName = " + selectedOsName);
        var osCompare = (os.name == this.selectedServer());
        console.log("osCompare is " + osCompare);
    }, this);

    total = total + selectedServerObject.price + selectedOsObject.price;

    return total;
},this);

Update

My updated fiddle is here: fiddle here

Thanks to d.raev it appears when the second log line is added console.log(selectedServerObject.price, the arrayFirst function starts being called with selectedServer = undefined.

server.name = DELL R210
selectedServerName = undefined
serverCompare is false
server.name = DELL R710
selectedServerName = undefined
serverCompare is false
server.name = DELL R720 Dual CPU
selectedServerName = undefined
serverCompare is false
os.name = Windows Standard
selectedOsName = undefined
osCompare is false
os.name = Windows Enterprise
selectedOsName = undefined
osCompare is false
os.name = CentOS Linux
selectedOsName = undefined
osCompare is false
os.name = Debian
selectedOsName = undefined
osCompare is false
1.  Uncaught TypeError: Cannot read property 'price' of null 

The undefined value from the selectedOsName or selectedServerName is causing the total to fail, what is the reason they are being set as undefined?

4

2 回答 2

2

您的脚本运行此函数 2 次,添加第二个 Debug 显示更清晰:

var selectedServerObject = ko.utils.arrayFirst(this.server, function(server){
    console.log("server.name = " + server.name);
    console.log("selectedServer = " + this.selectedServer());
    return server.name ==  this.selectedServer();
}, this); 

输出:


server.name = DELL R210
selectedServer = undefined
server.name = DELL R710
selectedServer = undefined
server.name = DELL R720 Dual CPU
selectedServer = undefined
null (selectedServerObject)
...
server.name = DELL R210
selectedServer = DELL R210
Object {name: “DELL R210”,规格:“1 x 2.4GHz 四核 CPU 4GB RAM
2 x 300GB SAS 15k”,价格:100}


只需添加一个检查 selectedServerObject 是否已设置 .. 或查找它被调用 2 次的原因:

例子:

if(selectedServerObject){
   total = total + selectedServerObject.price;
}
于 2013-07-18T09:10:56.877 回答
0

Fiddle here http://jsfiddle.net/g18c/2SAxR/2/显示了 d.raev 的怀疑是正确的 :) 我创建了原始代码的精简版本,当 selectedServer 未定义时调用描述计算函数,导致一切轰炸。

我已将 d.raev 的回复标记为答案,因为它找到了根本原因 - 很高兴了解这种 knockoutjs 行为以完全关闭。

<div data-bind="foreach: server">
    <div>
        <input type="radio" name="server" data-bind="attr: {value: sku}, checked: $root.selectedServer" />
        <span data-bind="text: name"></span>
    </div>
</div>
<p data-bind="text: selectedServer"></p>
<p data-bind="text: description"></p>

var serverOptions = [{
    name: "One",
    sku: 1000,
    specification: "yes",
    price: 100
}, {
    name: "Two",
    sku: 1001,
    specification: "hello",
    price: 200
}, {
    name: "Three",
    sku: 1002,
    specification: "wow",
    price: 300
}];

viewModel = function() {
    var self = this;
    self.server = serverOptions;
    self.selectedServer = ko.observable();
    self.description = ko.computed(function () {
        var selectedSku = this.selectedServer();
        if(typeof selectedSku == "undefined")
        {
            console.log("we are not fully bound, bombing out here...");
            return;
        }

        var found = ko.utils.arrayFirst(serverOptions, function (item) {
            var result = (item.sku == selectedSku);
            console.log("arrayFirst check => item.sku = " + item.sku + " selectedSku = " + selectedSku + ". result = " + result );
            return result;
        }, this);

        var textDescription = found.name + " - " + found.specification + " (" + found.price + ")";

        return textDescription;
    }, this);

    return self;
};

ko.applyBindings(new viewModel());
于 2013-07-18T15:51:26.933 回答