2012-12-19 12 views
5

Ho un modello di visualizzazione che deve essere collegato a un evento click di un tag <li>. Ecco il ViewModel e markupIl binding ad eliminazione diretta non è definito per il clic

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

E il markup è

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

Il problema è in questa linea

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

e

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

sia la linea sopra è non essere collegato allo Navigate e rispettivamente chosenFolderId osservabili. Dice Navigate non è definito. Non può essere analizzato . Same goes for sceltoFolderId`.

Qualche idea sul perché sta succedendo?

risposta

10

avete un paio di problemi con il tuo approccio attuale:

quando si utilizza un foreach binding es data-bind="foreach:Folders" dentro le ul il "contesto currect" saranno gli elementi nella vostra collezione cartella.

Quindi, se si vuole accedere ai navigate oi chosenFolderId metodi è necessario utilizzare $parent, o $root per accedere al vostro ViewModel "root" (si può leggere di più sul 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>​ 

È avere qualche problema anche nel tuo modello di vista. Se si dispone di funzioni complesse come navigate che cerca di utilizzare self si dovrebbe usare una funzione come ViewModel, invece di un oggetto letterale dove è possibile memorizzare 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());​ 

Nota che: la funzione navigate ha bisogno di un parametro folder fare funziona e Knockout passerà l'elemento corrente per te.

Questo è un working JSFiddle.

Se vuoi farlo con un oggetto letterale come il tuo modello di vista qui è JSFiddle che dimostra tale approccio.

Tuttavia, è necessario essere consapevoli di quali sono la forza e le settimane del metodo di creazione del modello a due viste. Questa domanda SO lo riassume bene: Difference between knockout View Models declared as object literals vs functions

+0

Sì, l'ho già fatto con questo approccio ricercato. Ma volevo farlo con un pattern modulare invece di spingere semplicemente i binding attraverso le funzioni. Quindi con il tuo approccio perfettamente valido. Non posso fare lo stesso con il mio approccio? – Joy

+0

@Joy Non ti seguo davvero ... puoi organizzare il tuo modellino di vista creando una funzione con il modello modulare. Puoi aggiornare il mio jsfiddle con il codice come lo immagini? – nemesv

+0

@Joy Esistono alcuni modi per farlo funzionare con i letterali degli oggetti come questo: http://jsfiddle.net/8Y5cv/1/. Ma alla fine incontrerai alcuni casi in cui non sarà sufficiente per le tue esigenze. – nemesv

Problemi correlati