Cupple Kay
Cupple Kay

Reputation: 155

KnockoutJs Visible doesn't work

I want a <td> to be visible or invisible depending on a boolean value in my javascript.

My HTML is:

<!-- ... -->
<tbody data-bind="foreach: entries">
    <tr>
        <td data-bind="visible: editable()">
            <a href="#" data-bind="click: $root.removeEntry">Remove</a>
        </td>  
    </tr>    
</tbody>
<!-- ... -->

And my Javascript would be this:

//...
function TableEntryViewModel(){
    editable: ko.observable(false);
    //...
}

When it loads my data it only loads the first entry and then stops. Here's the error i get.

Uncaught TypeError: Unable to process binding "visible: function (){return editable() }" Message: string is not a function

This isn't an exact replica of my programm, but if you make this work i'm sure you'll help me a lot: http://jsfiddle.net/CuppleKay/S6Hwa/

Upvotes: 0

Views: 1126

Answers (3)

Paul
Paul

Reputation: 1502

Ok, I can see from your example what you're trying to do. I've posted a modified version here:

http://jsfiddle.net/S6Hwa/2/

JavaScript:

function TableEntryViewModel(){
    var self = this;

    self.editable = ko.observable(false);

    self.removeEntry = function (row) {
        self.entries.remove(row);
    };

    self.entries = ko.observableArray([
        {name: "Hendrik", vorname: "Alex", adresse: "Southstreet", wohnort: "South", id: "239"},
        {name: "Hendrik", vorname: "Alex", adresse: "Southstreet", wohnort: "South", id: "240"},
        {name: "Hendrik", vorname: "Alex", adresse: "Southstreet", wohnort: "South", id: "241"}
    ]);
}

var model = new TableEntryViewModel();

ko.applyBindings(model);

HTML:

...
<td data-bind="visible: $root.editable"><a href="#" data-bind="click: $root.removeEntry">Remove</a>    </td>
...

Note that I needed to change your binding to $root.editable. If you want to hide "Remove" on a row-by-row basis, then try the slightly different version:

http://jsfiddle.net/S6Hwa/3/

JavaScript:

function TableEntryViewModel(){
    var self = this;

    self.removeEntry = function (row) {
        self.entries.remove(row);
    };

    self.entries = ko.observableArray([
        {name: "Hendrik", vorname: "Alex", adresse: "Southstreet", wohnort: "South", id: "239", editable: ko.observable(false)},
        {name: "Hendrik", vorname: "Alex", adresse: "Southstreet", wohnort: "South", id: "240", editable: ko.observable(false)},
        {name: "Hendrik", vorname: "Alex", adresse: "Southstreet", wohnort: "South", id: "241", editable: ko.observable(false)}
    ]);
}

var model = new TableEntryViewModel();

ko.applyBindings(model);

HTML:

...
<td data-bind="visible: editable"><a href="#" data-bind="click: $root.removeEntry">Remove</a>    </td>
...

Note that because each entry in your observableArray contains an editable value, we don't need to use $root. anymore.

Hope that helps.

Upvotes: 1

G&#244;T&#244;
G&#244;T&#244;

Reputation: 8053

This syntax is incorrect:

function TableEntryViewModel(){
    editable: ko.observable(false);
    //...
}

It should be either

function TableEntryViewModel(){
    this.editable = ko.observable(false);
    //...
}
//...
ko.applyBindings(new TableEntryViewModel());

Or

var TableEntryViewModel = {
    editable: ko.observable(false),
    //...
}
//...
ko.applyBindings(TableEntryViewModel);

Upvotes: 0

300 baud
300 baud

Reputation: 1672

This error can occur if you are not providing the correct context. Are your <td> elements inside a KO foreach?

For example:

<table data-bind="foreach: items">
  <tr>
    <td data-bind="visible: editable()">
      <a href="#" data-bind="click: $root.removeEntry">Remove</a>
    </td>
  </tr>
</table>

In this example, the context within the foreach is items and not the parent ViewModel. If editable exists in the parent ViewModel then you need to provide that context like so:

<td data-bind="visible: $parent.editable()">

Upvotes: 0

Related Questions