Here is a basic ViewModel structure:
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
});
});
}
}
This ViewModel is being applied to the following markup:
<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>
The issue arises when the afterRender
event of the foreach
binding is only triggered once, which happens after ko.applyBindings
. However, the DOM is not yet ready for us to initialize the jQuery.ui
draggable functionality.
According to Knockout documentation, afterRender
should be fired every time there is a change in the observableArray
associated with the corresponding foreach loop, but that is not occurring in this case.
I managed to make it work by initializing the draggable feature within the ajax.done
function after populating the array. Despite this workaround, I believe there might be a better way to handle this situation, and the core problem of afterRender
not triggering upon array update still remains.
If you have any suggestions or solutions, they would be greatly appreciated.
PS: When referring to "array," I am obviously talking about ko.observableArray