2013-01-10 9 views
42

Ho implementato un binding foreach a eliminazione diretta, con più modelli nella stessa pagina, uno degli esempi qui riportati, quello che mi interessa è scoprire quando termina un blocco rendering, ho provato afterRender e afterAdd, ma suppongo che venga eseguito per ogni elemento, e non dopo che l'intero ciclo è finito.callback successo dopo knockout.js termina il rendering di tutti gli elementi

<ul data-bind="foreach: {data: Contacts, afterAdd: myPostProcessingLogic}"> 
    <li> 
    <div class="list_container gray_bg mrgT3px"> 
     <div class="list_contact_icon"></div> 
     <div class="contact_name"><span data-bind="text: first_name"></span> <span data-bind="text: last_name"></span></div> 
     <div class="contact_number"><span data-bind="text: value"></span></div> 
     <div class="callsms_container"> 
     <a href="#notification-box" class="notifcation-window"> 
      <div class="hover_btn tooltip_call"> 
      <div class="hover_call_icon"></div> 
      <span>Call</span></div> 
     </a> 
     <a class="sendsms" href="#sendsms" rel="#sendsms"> 
      <div class="hover_btn tooltip_sms"> 
      <div class="hover_sms_icon"></div> 
      <span>SMS</span></div> 
     </a> 
     <a href="#"> 
      <div class="hover_more_btn"></div> 
     </a> 
     </div> 
     <!-- close callsms container --> 
     <div id="notification-box" class="notification-popup"> 
     <a href="#" class="close"><img class="btn_close" src="images/box_cross.png" /></a> <img class="centeralign" src="images/notification_call.png" /> <span>Calling... +44 7401 287366</span> </div> 
     <!-- close notification box --> 
     <!-- close list gray bg --> 
     <div class="tooltip_description" style="display:none" id="disp"> asdsadaasdsad </div> 
    </div> 
    </li> 
</ul> 

Sono interessato a scoprire solo il callback di successo, quando un ciclo termina il rendering.

Questa è la mia funzione afterAdd, che in pratica associa alcuni eventi jQuery e poco.

myPostProcessingLogic = function(elements) { 
    $(function(){ 
     $(".list_container_callog").hover(function(){ 
      $(".callsms_container", this).stop().animate({left:"0px"},{queue:false,duration:800}); 
     }, function() { 
      $(".callsms_container", this).stop().animate({left:"-98%"},{queue:false,duration:800}); 
     }); 
    }); 
} 

grazie in anticipo, e dimmi c'è un callback successo :)

risposta

62

Hai la afterRender richiamata in knockout.js:

foreach: { data: myItems, afterRender: renderedHandler } 

Here's documentation.

All'interno del vostro gestore di verificare se la lunghezza della raccolta renderizzata è uguale alla lunghezza della raccolta articoli. In caso contrario, non eseguire la logica di rendering completa che si intende utilizzare.

renderedHandler: function (elements, data) { 
    if ($('#containerId').children().length === this.myItems().length) { 
     // Only now execute handler 
    } 
} 
+2

l'ho già usato. il problema è che ha richiamato dopo ogni rendering di elementi, mentre sono interessato a scoprire quando tutti gli elementi finiscono il rendering – rohitarora

+0

@ user1487459 Ho aggiornato la risposta per il caso specifico. –

+0

sì è lo stesso ho una matrice di 10 elementi e il suo rendering 10 volte.Il problema che sto ottenendo è dopo ogni singolo rendering che esegue il js con ogni elemento che voglio solo che venga eseguito dopo che tutti gli elementi sono stati visualizzati. – rohitarora

1

La soluzione di cui sopra funziona alla grande. Inoltre, se hai bisogno di usare il foreach "come" opzione che si può fare come così:

data-bind="foreach: { data: myItems, afterRender: renderedHandlet, as: 'myItem'}"> 
9

Provare avvolgendo il ul con

<div data-bind='template: {afterRender: myPostProcessingLogic }'> 

funzionerà solo la prima volta tutto all'interno del modello è reso. Ma riceverai solo una chiamata a myPostProcessingLogic. Ecco un fiddle

<div data-bind='template: {afterRender: myPostProcessingLogic }'> 
    <ul data-bind="foreach: Contacts"> 
    <li> 
     <div class="list_container gray_bg mrgT3px"> 
     <div class="list_contact_icon"></div> 
     <div class="contact_name"><span data-bind="text: first_name"></span> <span data-bind="text: last_name"></span></div> 
     <div class="contact_number"><span data-bind="text: value"></span></div> 
     <div class="callsms_container"> 
      <a href="#notification-box" class="notifcation-window"> 
      <div class="hover_btn tooltip_call"> 
       <div class="hover_call_icon"></div> 
       <span>Call</span></div> 
      </a> 
      <a class="sendsms" href="#sendsms" rel="#sendsms"> 
      <div class="hover_btn tooltip_sms"> 
       <div class="hover_sms_icon"></div> 
       <span>SMS</span></div> 
      </a> 
      <a href="#"> 
      <div class="hover_more_btn"></div> 
      </a> 
     </div> 
     <!-- close callsms container --> 
     <div id="notification-box" class="notification-popup"> 
      <a href="#" class="close"><img class="btn_close" src="images/box_cross.png" /></a> <img class="centeralign" src="images/notification_call.png" /> <span>Calling... +44 7401 287366</span> </div> 
     <!-- close notification box --> 
     <!-- close list gray bg --> 
     <div class="tooltip_description" style="display:none" id="disp"> asdsadaasdsad </div> 
     </div> 
    </li> 
    </ul> 
</div> 
+0

Grazie per la soluzione molto bella e pulita. –

4

Basta avvolgere il foreach in un altro ciclo foreach utilizzando contenitore meno il metodo di Knockout come questo:

<!-- ko foreach:{data: Contacts, afterRender: myPostProcessingLogic }--> 
<ul data-bind="foreach: $data}"> 
    <li> 
    <div class="list_container gray_bg mrgT3px"> 
     <div class="list_contact_icon"></div> 
     <div class="contact_name"><span data-bind="text: first_name"></span> <span data-bind="text: last_name"></span></div> 
     <div class="contact_number"><span data-bind="text: value"></span></div> 
     <div class="callsms_container"> 
     <a href="#notification-box" class="notifcation-window"> 
      <div class="hover_btn tooltip_call"> 
      <div class="hover_call_icon"></div> 
      <span>Call</span></div> 
     </a> 
     <a class="sendsms" href="#sendsms" rel="#sendsms"> 
      <div class="hover_btn tooltip_sms"> 
      <div class="hover_sms_icon"></div> 
      <span>SMS</span></div> 
     </a> 
     <a href="#"> 
      <div class="hover_more_btn"></div> 
     </a> 
     </div> 
     <!-- close callsms container --> 
     <div id="notification-box" class="notification-popup"> 
     <a href="#" class="close"><img class="btn_close" src="images/box_cross.png" /></a> <img class="centeralign" src="images/notification_call.png" /> <span>Calling... +44 7401 287366</span> </div> 
     <!-- close notification box --> 
     <!-- close list gray bg --> 
     <div class="tooltip_description" style="display:none" id="disp"> asdsadaasdsad </div> 
    </div> 
    </li> 
</ul> 
<!-- /ko --> 
0

Sono appena fatto una richiesta di pull con knockout per loro di aggiungere due eventi definire nell'associazione, scartare, quindi chiamare negli spot corretti prima di rendere gli oggetti e dopo che tutti gli oggetti sono stati renderizzati. Non ho sentito nulla da loro ma questo fa esattamente quello che vuoi fare ma non devi scrivere codice hacky per farlo funzionare. Sono sorpreso che nessuno abbia mai fatto questa richiesta prima. Ho usato questi callback che ho aggiunto al sorgente per distruggere e reinizializzare un jQuery databile rilegato ad eliminazione diretta. Questa era la soluzione più semplice. Ho visto molti tentativi online che cercano di farlo in modo diverso, ma questa è la soluzione più semplice.

richiesta di pull: ->pr 1856

ko.bindingHandlers.DataTablesForEach = { 

    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
    var nodes = Array.prototype.slice.call(element.childNodes, 0); 
    ko.utils.arrayForEach(nodes, function(node) { 
     if (node && node.nodeType !== 1) { 
     node.parentNode.removeChild(node); 
     } 
    }); 
    return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); 
    }, 
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 

    var value = ko.unwrap(valueAccessor()), 
     key = "DataTablesForEach_Initialized"; 

    var newValue = function() { 
     return { 
     data: value.data || value, 
     beforeRenderAll: function(el, index, data) { 

      if (ko.utils.domData.get(element, key)) { 

      $(element).closest('table').DataTable().destroy(); 
      } 
     }, 
     afterRenderAll: function(el, index, data) { 
      $(element).closest('table').DataTable(value.options); 
     } 
     }; 
    }; 

    ko.bindingHandlers.foreach.update(element, newValue, allBindingsAccessor, viewModel, bindingContext); 

    //if we have not previously marked this as initialized and there is currently items in the array, then cache on the element that it has been initialized 
    if (!ko.utils.domData.get(element, key) && (value.data || value.length)) { 
     ko.utils.domData.set(element, key, true); 
    } 

    return { 
     controlsDescendantBindings: true 
    }; 
    } 
}; 

Knockout Datatables JSFiddle

1

risposta di Chuck Schneider sopra è il migliore. Ho dovuto usare il controllo containerless come il foreach è su un elemento tbody:

<!-- ko template: {afterRender: SetupCheckboxes } --> 
<tbody data-bind="foreach: selectedItems" id="gridBody"> 
    <tr> 
    <td> 
     <input type="checkbox" /> 
    </td> 
    </tr> 
</tbody> 
<!-- /ko --> 
0

Prova afterRenderAll richiamata in knockout.js:

foreach: {dati: myItems, afterRenderAll: myPostProcessingLogic}

Problemi correlati