2017-02-21 2 views
0

Ich habe diese einfache Ansichtsmodell:Knockout afterRender feuert nur einmal

export class ViewModel { 
    public arr : KnockoutObservableArray<Dtos>; 
    constructor() { 
     this.arr = ko.observableArray<Dtos>(null); 
     ko.applyBindings(this); 
     this.init(); 
    } 

    private init() { 
     var self = this; 
     ajaxCall().done(item => { 
       self.arr(item.Dtos);     
      }); 
    } 

    public initPlugins() { 
     jQuery(".external-events > li") 
      .each(function() { 
       if ($(this).attr("event-draggable") == "false") 
        return true; 
       jQuery(this).draggable({ 
       zIndex: 999, 
       revert: true, // will cause the event to go back to its 
       revertDuration: 0 // original position after the drag 
      }); 
     }); 
    } 
} 

Diese vm auf diese Markup angewendet wird immer:

<ul class="external-events" data-bind="foreach: {arr, afterRender: initPlugins($data)}"> 
    <li event-draggable="false"> 
     <div class="bg-info"> 
      <span data-bind="text: Name"></span> 
     </div> 
     <ul class="external-events" data-bind="foreach: moreStuff"> 
      <li> 
       <div class="bg-info"> 
        <span data-bind="text: Name"></span> 
       </div> 
      </li> 
     </ul> 
    </li> 
</ul> 

Das Problem ist, dass das afterRender Ereignis des foreach nur verbindlich ist einmal ausgelöst, offensichtlich nach ko.applyBindings, aber das DOM ist noch nicht fertig, so dass wir die jQuery.ui nicht ziehbar auslösen können.

Laut Ko Dokumentation, afterRender sollte jedes Mal feuern, wenn die observableArray (gehört zu den entsprechenden foreach) ändert, aber es ist nicht passiert.

Schließlich habe ich es funktioniert durch die Initialisierung der ziehbaren in der ajax.done, nachdem ich das Array zu füllen, aber ich fühle mich wie es ist nicht der richtige Weg, und dennoch besteht das Problem weiterhin, afterRender nicht auf Array-Update feuern.

Alle Ideen würden sehr geschätzt werden.

PS: Array ich meine natürlich ko.observableArray

Antwort

1

Das Problem ist in Ihrem

foreach: {arr, afterRender: initPlugins($data)} 

afterRender eine Funktion als Parameter erwartet, aber Sie werden den Aufruf der Funktion indem sie sie mit Daten als Parameter, ändern Aufruf es:

foreach: {arr, afterRender: initPlugins } 

afterRender Methode wird mit 2 Parametern durch Knockout aufgerufen werden:

Ein Array der eingefügten DOM-Elemente, das Datenelement, gegen das sie gebunden werden

+0

danke, es funktioniert! Gibt es eine saubere Möglichkeit, auf das ViewModel im afterRender zuzugreifen? –