2012-12-19 13 views
5

Mam model widoku, który musi być dołączony do zdarzenia kliknięcia znacznika <li>. Oto ViewModel i znacznikówWiązanie knockout jest niezdefiniowane dla kliknięcia

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

A znaczników jest

<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> 

Problem jest w tym wierszu

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

i

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

Zarówno linia powyżej jest nie przywiązuje się do Navigate funkcja i odpowiednio obserwowane chosenFolderId. Mówi, że Navigate jest niezdefiniowany. Nie można go przeanalizować: . Same goes for selectedFolderId`.

Każdy pomysł, dlaczego to się dzieje?

Odpowiedz

10

masz kilka problemów z obecnego podejścia:

Kiedy używasz foreach binding np data-bind="foreach:Folders" wewnątrz firmy ul z „currect kontekst” zostanie pozycji w swojej kolekcji folderów.

Więc jeśli chcesz uzyskać dostęp do lub metod navigatechosenFolderId musisz użyć $parent lub $root aby uzyskać dostęp do Twojego „root” ViewModel (można przeczytać więcej na temat 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>​ 

Ty Mam również problem w twoim modelu widoku. Jeśli masz złożonych funkcji jak navigate który stara się wykorzystać self należy użyć funkcji jako viewmodel zamiast obiektu dosłownym gdzie można przechowywać 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());​ 

zauważyć, że: czynność navigate potrzebuje parametru folder aby to działa, a Knockout przekaże ci bieżący przedmiot.

Oto working JSFiddle.

Jeśli chcesz zrobić to z literałem obiektu, ponieważ twój model widoku jest tutaj JSFiddle, który demonstruje to podejście.

Powinieneś jednak wiedzieć, jaka jest siła i tygodniowość podejścia do tworzenia dwóch poglądów na model. To pytanie SO podsumowuje to dobrze: Difference between knockout View Models declared as object literals vs functions

+0

Tak, już to zrobiłem z tym poszukiwanym podejściem. Ale chciałem, aby to zrobiło z modularnym wzorcem zamiast po prostu przepychać wiązania przez funkcje. Tak więc Twoje podejście jest całkowicie poprawne. Czy nie mogę zrobić tego samego z Moim podejściem? – Joy

+0

@Joy Naprawdę nie podążam za tobą ... możesz zorganizować swoją funkcję tworzenia viewmodelu o strukturze modułowej. Czy możesz zaktualizować mój jsfiddle kodem, jak sobie to wyobrażasz? – nemesv

+0

@Joy Istnieje kilka sposobów na to, aby działało to z literałami obiektowymi w następujący sposób: http://jsfiddle.net/8Y5cv/1/. Ale w końcu napotkasz kilka przypadków, w których to nie wystarczy dla twoich potrzeb. – nemesv

Powiązane problemy