Norbert
Norbert

Reputation: 2771

Handling non-existent observableArray properties in the view in KnockoutJS

How do I show an observableArray's property in the view without getting a ReferenceError when that property disappears?

For example, I have the following observableArray:

this.arr({a:1, b:2, c: ['qwe', 'qweq'], d:4});

And I'm trying to show the length of c in the view:

<div data-bind="with: arr()">
  <div data-bind="text: c.length"></div>
</div>

This works on page load, but when I empty the array, I'm getting the ReferenceError in the console.

Example: http://jsfiddle.net/074pxwzt/

Is there a way to just ignore the property in case it doesn't exist?

Upvotes: 1

Views: 71

Answers (2)

janfoeh
janfoeh

Reputation: 10328

The with binding does not bind its children if the property does not exist / is null.

I am confused as to why you set the observableArray to an object, though — it seems you should either use an observable for this, or actually use it as an array.

Version with observable:

var ViewModel = function() {
  var self = this;

  this.arr = ko.observable();

  this.arr({
    a: 1,
    b: 2,
    c: ['qwe', 'qweq'],
    d: 4
  });

  this.kill = function() {
    self.arr(null);
  }

};

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div>

  <button data-bind="click: kill">Kill</button>

  <br>
  <br>

  <div data-bind="with: arr">
    <div data-bind="text: c.length"></div>
  </div>
</div>

Version with observableArray:

var ViewModel = function() {
  var self = this;

  this.arr = ko.observableArray([]);

  this.arr.push({
    a: 1,
    b: 2,
    c: ['qwe', 'qweq'],
    d: 4
  });

  this.kill = function() {
    self.arr.removeAll();
  }

};

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div>

  <button data-bind="click: kill">Kill</button>

  <br>
  <br>

  <div data-bind="foreach: arr">
    <div data-bind="text: c.length"></div>
  </div>
</div>

Upvotes: 2

4imble
4imble

Reputation: 14416

This seems to work for your specific case. However if you set the array to null using this code then it will then error.

var ViewModel = function() {
  var self = this;

  this.arr = ko.observableArray();

  this.arr({
    a: 1,
    b: 2,
    c: ['qwe', 'qweq'],
    d: 4
  });

  this.kill = function() {
    self.arr([]);
  }

  this.swap = function() {
    self.arr({
      a: 1,
      b: 2,
      x: ['qwe', 'qweq', 'ijdj'],
      d: 4
    });
  }

};

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div>
  <button data-bind="click: kill">Kill</button>
  <button data-bind="click: swap">Swap</button>
  <div data-bind="with: arr().c">
    <div data-bind="text: length"></div>
  </div>
  <div data-bind="with: arr().x">
    <div data-bind="text: length"></div>
  </div>
</div>

Upvotes: 0

Related Questions