6

I have a view model Which has to be attached to a click event of an <li> tag. Here is the viewmodel and markup

  var viewModel =
    {
        Folders: ['Inbox', 'Archive', 'Sent', 'Spam'],
        SelectedFolder: ko.observable('Inbox'),
        chosenFolderId: ko.observable(),
        navigate: function () {
            self.chosenFolderId(folder);               
        }
    };
ko.applyBindings(viewModel);

And the markup is

   <ul class="nav nav-list bs-docs-sidenav affix" data-bind="foreach:Folders">
                @*<li data-bind="css:{active: $data == chosenFolderId() }">*@
                <li>
                    <a href="#" data-bind="click:navigate">                      
                        <!-- ko text: $data -->
                        <!-- /ko -->
                        <i class="icon-chevron-right"></i>
                    </a>
                </li>                   
            </ul>

The problem is in this line

<a href="#" data-bind="click:navigate"> 

and

<li data-bind="css:{active: $data == chosenFolderId() }">

Both The line above is not getting attached to the Navigate function and chosenFolderId observable respectively. It says Navigate is undefined . It cannot be parsed. Same goes forchosenFolderId`.

Any idea why is it happening ?

Joy
  • 6,438
  • 8
  • 44
  • 75

1 Answers1

14

You have a few problems with your current approach:

When you use a foreach binding e.g data-bind="foreach:Folders" inside your ul the "currect context" will be the items in your folder collection.

So if you want to access the navigate or the chosenFolderId methods you need to use $parent, or $root to access the your "root" viewmodel (you can read more about the binding context):

<ul class="nav nav-list bs-docs-sidenav affix" data-bind="foreach:Folders">
    <li data-bind="css:{active: $data == $parent.chosenFolderId() }">
        <a href="#" data-bind="click: $parent.navigate">                      
            <!-- ko text: $data -->
            <!-- /ko -->
            <i class="icon-chevron-right"></i>
        </a>
    </li>                   
</ul>​

You have some problem in your view model as well. If you have complex functions like navigate which tries to use self you should use a function as a viewmodel instead of an object literal where you can store this:

var viewModel = function() {
    var self = this;
    self.Folders = ['Inbox', 'Archive', 'Sent', 'Spam'];
    self.SelectedFolder = ko.observable('Inbox');
    self.chosenFolderId = ko.observable();
    self.navigate = function(folder) {
        self.chosenFolderId(folder);
    }
};
ko.applyBindings(new viewModel());​

Note that: your navigate function needs a folder parameter to make it work and Knockout will pass the current item for you.

Here is a working JSFiddle.

If you want to do it with an object literal as your view model here is JSFiddle which demonstrates that approach.

However you should be aware what are the strength and weeknesses of the two view model creation approach. This SO question summarizes it well: Difference between knockout View Models declared as object literals vs functions

Community
  • 1
  • 1
nemesv
  • 138,284
  • 16
  • 416
  • 359
  • Yes I already did that with this sought of approach . But I wanted it to do with modular pattern instead of just pushing the bindings through functions . So With your approach perfectly valid . Can't I do the same with My approach ? – Joy Dec 19 '12 at 06:06
  • @Joy I don't really following you... you can organize your viewmodel creating function with the modular pattern. Can you maybe update my jsfiddle with the code how you imagine it? – nemesv Dec 19 '12 at 06:11
  • @Joy There are a few way to make it work with object literals like this: http://jsfiddle.net/8Y5cv/1/. But you will eventually encounter some cases where it won't be enough for your needs. – nemesv Dec 19 '12 at 06:18
  • yes the last fiddle which you provided . I actually wanted to put in that way . Well I am pretty novice in knockout as of now . Can you tell why object literals wont alwayz fit for my needs ? or with a good blog post regarding this ? Sorry If I am too naive in asking this – Joy Dec 19 '12 at 06:30
  • 1
    @Joy there is a good SO question about it: http://stackoverflow.com/questions/9589419/difference-between-knockout-view-models-declared-as-object-literals-vs-functions. Also the plurasight courses on KO are quite good altough they are not free. – nemesv Dec 19 '12 at 06:40