The knockout afterRender event triggers only on the initial rendering

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

Answer №1

The issue lies within your code

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

It appears that the afterRender function is being incorrectly called with data as a parameter instead of just passing it as a reference. Try changing it to:

foreach: {arr, afterRender: initPlugins }

Knockout's afterRender method expects 2 parameters:

An array representing the DOM elements that were inserted, along with the corresponding data item they are bound to

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can we eliminate all elements from jQuery except for the first and second elements?

HTML <div class="geo_select"> <h3>header 3</h3> in Above HTML code i want to remove all element except <h3> and default content<div> inside the <div class='geo_select'> in jquery.. How to remove all ...

Having difficulty encapsulating three.js rendered particles within a single div

I'm facing an issue where the particles generated by my three.js project are not contained within a specific div or html element as intended. Instead of staying within the designated boundaries, the particles are spreading across the entire DOM witho ...

Swap Text/Characters When Hovered Over

I'm looking to add a fun interactive element to my webpage where the letters in certain text rearrange when a user hovers over it. For instance, hovering over "WORK" would display "OWKR" instead. I have a feeling that some JavaScript is needed for thi ...

Update image source dynamically using AJAX and jQuery

Within my app, there exists a web page that contains numerous images with dynamically generated source URLs obtained by sending get requests to the rails server. Initially, these images are assigned a default source. Upon loading the page, another request ...

React - optimize performance by preventing unnecessary re-renders of an object property

In my current project, I am working with an auction object that has two properties: remainingTime and amount. To enhance user experience, I integrated a countdown timer using the react-countdown-now library to display the remainingTime. Additionally, there ...

Regain Identification or Data using PHP, JavaScript, and MySQL

I'm currently working on a project and I'm facing a challenge in retrieving Id either in php or js. I have 2 rows in the same table in mySql: row 1 = id_answer and row 2 = text. I am using a foreach loop in my code to extract the text from the ...

Breaking down an array into alphabetical sections using React and Typescript

I have a large array of strings containing over 100 words. I have already sorted the array in alphabetical order, but now I need to group or split the array into a hash array called hashMap<String(Alphabet), List<String>>. This will allow me to ...

How can we ensure that href/src values are "absolutized" when utilizing server rendering?

Imagine having an element with its href/src set as a root path like this: href="/abc/def". There is also a function written like this: function absolutizeHREF(href) { const URLBase = new URL(`http://${process.env.HOST}:${process.env.PORT}/`); ...

Is there a way to use jQuery to centrally align the accordion item that I have chosen?

My attempts to use `this.scrollIntoView({behavior: "smooth"}) were yielding inconsistent results in terms of where the selected item would land on the page. I believe I might need to utilize scrollTop(), but as someone who is new to jQuery, I am ...

What is the best way to present retrieved JSON data from a database in Node.js without using the JSON format?

Here is the code snippet: var http=require("http"); var fs = require("fs"); var express = require("express"); var app = express(); var path = require("path"); var mysql = require('mysql'); var ejs = require("ejs") var bodyParser = require(&apos ...

Having trouble with Javascript/ajax/php: data is successfully sent from server to client, but client to server communication is not working as

Apologies for the duplicate post (Admins, kindly remove the other one!). I've been receiving great assistance from you all and was hoping to seek your help once again with the following question: I am currently working on implementing AJAX by allowin ...

Kohana ajax causing removal of JQuery Data attributes

Currently, I am developing an application where jquery data is used to pass variables to HTML elements. It has been successful in one part of the site when the data attributes are added to a tr tag. The following code works: <tr class="js-instructions ...

Is it possible to modify the font size of all text that shares a particular font size?

Lately, I've been pondering on a question. A few years ago, I created a website using regular CSS and now I want to make some changes to the font sizes. While I know that CSS variables are the recommended solution for this situation, I'm curious ...

Determining when a checkbox changes state using HTML and JavaScript

My main objective is to display divX2 when the checkbox for x2 is checked, either by directly clicking on x2 or by clicking on the "Check All" checkbox. The functionality works as intended when the checkbox for x2 is clicked, but it fails to work when the ...

Accessing an element using jQuery within a knockout event

I've recently started experimenting with knockout.js in combination with jQuery, and my experience with knockout.js is still quite limited. If you want to take a look at my code example, you can find it here: http://jsfiddle.net/Ninjanoel/ADYN6/ Cur ...

Guide to converting JSON data into object structures

Question - How do I convert JSON data into objects? You can find the JSON data here Details - After successfully connecting to the API and retrieving the JSON data, I am looking to map two arrays data.hourly.time[] and data.hourly.temperature_2m[] into a ...

Each loop in the forEach function triggers the mouseup event

I am currently utilizing a foreach loop: objects.forEach(function(object) { var button = '<tr><td>' + object.object.code + '</td><td>' + formatDistance(1456000) + &apos ...

Refreshing express-session sessions

My goal is to enhance the user experience by retrieving their profile from the mongodb database when they visit the page, and then updating their session with this information. Currently, I am utilizing the following packages for managing sessions: - ex ...

What steps can I take to ensure that this input is neat and tidy

I need to implement conditional styling for my input field. The current layout is chaotic and I want to improve it. Specifically, when the active item is "Height", I only want to display the height value and be able to change it using setHeight. const [a ...

Tips for verifying conditional input fields in a React component?

As a beginner in React, I attempted to create a SignIn form component that dynamically changes its layout based on a boolean prop toggled between Login and Signup options. In the signup version, there is an additional text field labeled Confirm password, w ...