最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Knockout Observable Array Length always 0 - Stack Overflow

programmeradmin1浏览0评论

When calling the length of any observable in the customerOverview view model I receive a length of zero. There is data present in the observables as the bindings update with data, however the length remains at 0. The base view model, 'CustomerCentral', returns lengths properly. I need the length of some observables in 'CustomerOverview' to do some conditional statements.

HTML Bindings

<ul class="nav nav-list">
      <li class="nav-header">Contacts</li>
      <!--ko  if: customerOverview.contacts().length == 0-->
      <li>No contacts associated with this customer</li>
       <!-- /ko -->
      <!--ko  foreach: customerOverview.contacts()-->
      <li>
      <a data-bind="click: $root.customerOverview.viewContact"><i class="icon-chevron-                        right single pull-right">
       </i><span data-bind="text: FirstName"></span><span data-bind="text: LastName"></span>
      </a></li>
      <!-- /ko -->
</ul>

JS

function CustomerOverview() {
        var self = this;        

        self.contacts = ko.observableArray([]);           

        self.getCustomerContacts = function () {
            requestController = "/CRM/CustomerCentral/CustomerContacts";
            queryString = "?id=" + self.customer().Id();
            $.ajax({
                cache: false,
                type: "GET",
                dataType: "json",
                url: baseURL + requestController + queryString,
                headers: { "AuthToken": cookie },
                success:
                        function (data) {
                            if (data.data.length > 0) {

                                self.contacts(ko.mapping.fromJS(data.data));

                                console.log(self.contacts().length);
                            }
                        }
            });
        };
};
   function CustomerCentral() {

        var self = this;

        self.customerOverview = ko.observable(new customerOverview());
};

var vm = new CustomerCentral();
    ko.applyBindings(vm);

Console cmd: vm.customerOverview().contacts().length 0

---------------------------SOLUTION ---------------------- observableArray.push()

The issue turned out to be this line :

  self.contacts(ko.mapping.fromJS(data.data));

SOLUTION: Adding .push() to this enabled the length property of the array to be incremented. I had assumed ko.mapping would handle this but it does not. Changing the variable to observable had no effect.

 $.each(data.data, function () {
          self.contacts.push(ko.mapping.fromJS(this));
           console.log(self.contacts().length);
                                    });

When calling the length of any observable in the customerOverview view model I receive a length of zero. There is data present in the observables as the bindings update with data, however the length remains at 0. The base view model, 'CustomerCentral', returns lengths properly. I need the length of some observables in 'CustomerOverview' to do some conditional statements.

HTML Bindings

<ul class="nav nav-list">
      <li class="nav-header">Contacts</li>
      <!--ko  if: customerOverview.contacts().length == 0-->
      <li>No contacts associated with this customer</li>
       <!-- /ko -->
      <!--ko  foreach: customerOverview.contacts()-->
      <li>
      <a data-bind="click: $root.customerOverview.viewContact"><i class="icon-chevron-                        right single pull-right">
       </i><span data-bind="text: FirstName"></span><span data-bind="text: LastName"></span>
      </a></li>
      <!-- /ko -->
</ul>

JS

function CustomerOverview() {
        var self = this;        

        self.contacts = ko.observableArray([]);           

        self.getCustomerContacts = function () {
            requestController = "/CRM/CustomerCentral/CustomerContacts";
            queryString = "?id=" + self.customer().Id();
            $.ajax({
                cache: false,
                type: "GET",
                dataType: "json",
                url: baseURL + requestController + queryString,
                headers: { "AuthToken": cookie },
                success:
                        function (data) {
                            if (data.data.length > 0) {

                                self.contacts(ko.mapping.fromJS(data.data));

                                console.log(self.contacts().length);
                            }
                        }
            });
        };
};
   function CustomerCentral() {

        var self = this;

        self.customerOverview = ko.observable(new customerOverview());
};

var vm = new CustomerCentral();
    ko.applyBindings(vm);

Console cmd: vm.customerOverview().contacts().length 0

---------------------------SOLUTION ---------------------- observableArray.push()

The issue turned out to be this line :

  self.contacts(ko.mapping.fromJS(data.data));

SOLUTION: Adding .push() to this enabled the length property of the array to be incremented. I had assumed ko.mapping would handle this but it does not. Changing the variable to observable had no effect.

 $.each(data.data, function () {
          self.contacts.push(ko.mapping.fromJS(this));
           console.log(self.contacts().length);
                                    });
Share Improve this question edited Dec 9, 2013 at 16:46 Strake asked Mar 21, 2013 at 18:47 StrakeStrake 7621 gold badge9 silver badges18 bronze badges
Add a comment  | 

5 Answers 5

Reset to default 6

I think your problem is not having your customerOverview property as observable

try:

 self.customerOverview = ko.observable(new CustomerOverview());

or

 self.customerOverview = ko.computed(function(){
       return new CustomerOverview();
 });

Working sample:

http://jsfiddle.net/dvdrom000/RHhmY/1/

html

<span data-bind="text: customerOverview().contacts().length"></span>
<button data-bind="click: customerOverview().getCustomerContacts">Get contacts</button>

js

function CustomerOverview() {
        var self = this;        

        self.contacts = ko.observableArray([]);           

        self.getCustomerContacts = function () {
            self.contacts.push(1);
            self.contacts.push(2);
            self.contacts.push(3);            
        };
};
   function CustomerCentral() {

        var self = this;
        // Is this a correct way. Am I breaking something with this?
        self.customerOverview = ko.observable(new CustomerOverview());
};

var vm = new CustomerCentral();
    ko.applyBindings(vm);

Knockout provides a set of manipulation functions for arrays that mirror the functions found in in JavaScript; pop, push, shift, unshift, reverse, sort, and splice. Along with performing the operations you’d expect, these array functions will also automatically notify any observers that the array has changed. The JavaScript methods wont. If you want your UI to update when the array counts change, you’ll want to be careful to use the Knockout functions.

Reference: http://ryanrahlf.com/knockout-js-observablearray-not-updating-the-ui-heres-how-to-fix-it/

So basically, to solve your problem, you just need to use the knockout push function directly on the observable array instead of using the javascript push method. Hence:

Change this:

self.contacts( ).push( data.data );

By this:

self.contacts.push( data.data );

And you will be able to use the contacts( ).length property on your html and be notified on every change in the array.

observableArray.push()

The issue turned out to be this line :

self.contacts(ko.mapping.fromJS(data.data));

SOLUTION: Adding .push() to this enabled the length property of the array to be incremented. I had assumed ko.mapping would handle this but it does not. Changing the variable to observable had no effect.

$.each(data.data, function () {
          self.contacts.push(ko.mapping.fromJS(this));
           console.log(self.contacts().length);
                                    });

I had problems like this, and IIRC, it was because I was using double equals (==) instead of triple equals (===) in the comment conditionals. Give it a shot.

Instead of:

self.contacts(ko.mapping.fromJS(data.data));

You should have:

self.contacts(ko.mapping.fromJS(data.data)**()**);
发布评论

评论列表(0)

  1. 暂无评论