web-dev-qa-db-fra.com

callback de succès après que knockout.js a fini de rendre tous les éléments

J'ai implémenté un knock-out foreach binding, avec plusieurs modèles dans la même page. L'un des exemples est donné ici. Ce qui m'intéresse, c'est de savoir quand un bloc se termine, j'ai essayé afterRender et afterAdd, mais je suppose que ça fonctionne pour chaque élément et non pas après la fin de la boucle.

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

Je suis intéressé à trouver juste le rappel de succès, quand une boucle termine le rendu.

voici ma fonction afterAdd, qui attache en gros des événements jQuery et rien de plus.

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});
      });
  });
}

merci d'avance, et dites-moi qu'il y a un rappel réussi :)

43
rohitarora

Vous avez le callback afterRender dans knockout.js:

foreach: { data: myItems, afterRender: renderedHandler }

Voici la documentation.

Dans votre gestionnaire, vérifiez si la longueur de la collection rendue est égale à la longueur de la collection d'éléments. Si ce n'est pas le cas, n'exécutez pas la logique de rendu complète que vous avez l'intention d'utiliser.

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

Essayez d’emballer la ul avec 

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

Cela ne fonctionnera que la première fois que tout le rendu dans le modèle est rendu. Mais vous ne recevrez qu'un seul appel à myPostProcessingLogic. Voici un violon

<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>
9
Chuck Schneider

Enroulez simplement le foreach dans une autre boucle foreach en utilisant la méthode de conteneur moins de Knockout comme ceci:

<!-- 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 -->
4
Sohail xIN3N

La réponse de Chuck Schneider ci-dessus est la meilleure. J'ai dû utiliser le contrôle sans conteneur car la foreach est sur un élément tbody:

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

La solution ci-dessus fonctionne très bien. De plus, si vous devez utiliser l'option for as "en tant que", vous pouvez le faire comme suit:

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

Je viens tout juste de faire une demande d'extraction avec knock-out pour qu'ils ajoutent deux événements à définir dans la liaison, dérouler, puis appeler les bons emplacements avant de rendre les éléments et après que tous les éléments aient été rendus. Je n'ai rien entendu de leur part, mais cela correspond exactement à ce que vous voulez faire, mais vous n'avez pas à écrire de code hacky pour le faire fonctionner. Je suis surpris que personne n'ait déjà fait cette demande. J'ai utilisé ces rappels que j'ai ajoutés à la source pour détruire et réinitialiser un jQuery datable lié au knock-out. C'était la solution la plus simple. J'ai vu de nombreuses tentatives en ligne qui tentent de le faire différemment, mais c'est la solution la plus simple.

Demande de tirage: -> 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

0
Zach Painter

Essayez de rappeler afterRenderAll dans knockout.js:

foreach: {data: myItems, afterRenderAll: myPostProcessingLogic}

0
Renon Stewart