2013-08-09 6 views
6

Vorrei creare un bind 'click condizionale' in KnockoutJS. Fondamentalmente si tratta di un bind di clic standard come lo si userebbe in Knockout, ma è necessario soddisfare una condizione per poter eseguire la funzione allegata. Nel mio caso, l'opzione migliore è quella di creare un bindinghandler personalizzato in cui quindi si chiama il bind di clic standard, se consentito.Chiama standard Binding a eliminazione diretta da un binding personalizzato

ko.bindingHandlers.safeClick = { 
    'init': function(element, valueAccessor, allBindingsAccessor, context) { 
     $(element).click(function() { 
      if(mycondition == true) { 
       // call the standard click binding here -> this is the part I don't know 
      } 
     }); 
    } 
} 

voglio sostituire tutti i miei attacchi fare clic su Standard con questa usanza vincolante. Pertanto è importante chiamare l'associazione di clic nel modo corretto, in modo che tutti i parametri forniti in HTML vengano passati alla funzione. Per esempio:

<a href="#" data-bind="click: basevm.gotopage.bind($data, '#homepage')">Home</a> 
<a href="#" data-bind="click: itemvm.activateItem">Activate</a> 

Questi devono essere sostituiti da

<a href="#" data-bind="safeClick: basevm.gotopage.bind($data, '#homepage')">Home</a> 
<a href="#" data-bind="safeClick: itemvm.activateItem">Activate</a> 

sarei molto grato se mi potesse aiutare con la parte mancante nel legame personalizzato.

risposta

11

Il modo corretto per delegare il click aspettando qui è la seguente:

  • si prende la funzione originale (ad esempio utilizzando valueAccessor())
  • creare una nuova funzione di attributo di valore in cui si restituisce una nuova funzione contenente la condizione che quindi chiama la funzione originale. E passare questo nuovo valueaccessor al binding click.

Così il vostro safeClick sarà simile a questa:

ko.bindingHandlers.safeClick = { 
    'init': function (element, valueAccessor, allBindingsAccessor, 
         viewModel, bindingContext) { 
     var originalFunction = valueAccessor(); 
     var newValueAccesssor = function() { 
      return function() { 
       if (mycondition == true) 
        //pass through the arguments 
        originalFunction.apply(viewModel, arguments); 
      } 
     } 
     ko.bindingHandlers.click.init(element, newValueAccesssor, 
      allBindingsAccessor, viewModel, bindingContext); 
    } 
} 

Demo JSFiddle.

Questo funzionerà per il primo clic e non è necessario iscriversi manualmente all'evento clic o attivarlo con jQuery.

+0

Questo metodo presuppone che si passi la condizione come Knockout osservabile nel codice HTML. Non desidero farlo. Invece, voglio controllare manualmente la condizione nel codice JavaScript ogni volta che si fa clic sull'elemento. Hai qualche consiglio su come farlo? –

+0

Puoi scrivere qualsiasi cosa desideri invece di 'if (condizione ko.utils.unwrapObservable (allBindingsAccessor().)'. Verrà valutato ogni volta che si fa clic sul collegamento. Avevo solo bisogno della condizione osservabile per il mio demo jsfiddle. Vedere questo violino modificato: http://jsfiddle.net/w7nKB/2/ – nemesv

+0

Ho creato questo violino (http://jsfiddle.net/Ed8Fc/) per illustrare il problema tra la normale associazione di clic e questa associazione personalizzata. Devo avere accesso all'elemento DOM che ha attivato l'evento click. Si vede che con la normale associazione dei clic questo è ok, ma con l'associazione safeClick c'è un errore segnalato nella console del browser. –

1

Si può chiamare come segue:

ko.bindingHandlers.click.init(element, valueAccessor, allBindingsAccessor, context); 

EDIT: È possibile mannualy chiamare cliccare evento prima volta:

ko.bindingHandlers.safeClick = { 
    'init': function(element, valueAccessor, allBindingsAccessor, context) { 
     $(element).click(function() { 
      if(mycondition == true) { 
       ko.bindingHandlers.click.init(element, valueAccessor, allBindingsAccessor, context); 
      } 
     }); 
     if(mycondition == true) { 
      $(element).trigger('click'); 
     } 
    } 
} 
+0

Mi sono già imbattuto in questo mentre cercavo sul web. Purtroppo ho scoperto che funziona solo dalla seconda volta che fai clic sull'elemento di ancoraggio. La mia soluzione deve funzionare dal primo clic dell'utente. –

+0

Vedere l'aggiornamento, spero che questo possa essere d'aiuto. –