Harness the Power of Asynchronous Binding in Knockout.js

I'm really struggling to figure out how to asynchronously bind my cascading Select2 drop-down fields using knockoutJS.

Everything works perfectly fine when the data is static within the function, but as soon as I introduce an asynchronous ajax call, the binding happens before the response is received and things fall apart.

If anyone could point me in the right direction or spot any issues, I would greatly appreciate it as I am fairly new to knockout.js.

Knockout

var viewModel = {
    togaMakers: buildData(),
    selectedInstitution : ko.observable(),
    selectedLevel : ko.observable(),
    selectedFaculty : ko.observable()
};

viewModel.togaLevels = ko.computed(function(){
    if(viewModel.selectedInstitution()){
        var make = ko.utils.arrayFirst(viewModel.togaMakers,function(item){
            //console.log(item.text,viewModel.selectedInstitution());
                return item.text===viewModel.selectedInstitution();          
        });
        return make.childOptions;
    } 
});

viewModel.togaFaculties = ko.computed(function(){
    if(viewModel.selectedLevel()){
        var type = ko.utils.arrayFirst(viewModel.togaLevels(),function(item){
            //console.log(item.text,viewModel.selectedLevel());
                return item.text===viewModel.selectedLevel();
          //console.log("Answer:" + item);
        });
        return type.childOptions;
    } 
});
ko.cleanNode(viewModel);
ko.applyBindings(viewModel);

buildData()

function buildData() {
    var gotData = getData();

    return gotData.then(function() {
        console.log('step 4 - return result');
        returnData = gotData;
        return returnData;
    });
}

getData()

// Fetch all data from an ajax call
function getData() {
    var data = { 'action': 'get_data' };
    var deferred = new jQuery.Deferred();

    return jQuery.post(ajaxurl, data, function(response) {
        // console.log(response);
        console.log('step 1 - parse ajax data');
        var obj = JSON.parse(response);
        console.log('step 2 - process received data');
        results = processData(obj);
    }).done(function() {
        console.log('step 3 - ajax parsing & processing data done');
        console.log(results);
        deferred.resolve(results);
        return deferred;
    }).fail(function() {
        console.log('fail');
    });
}

Answer №1

buildData should be modified to return an observable. This is necessary for the binding to automatically update when the data changes:

function buildData() {
  var dataContainer = ko.observableArray([]);

  getData().then(function(newData) {
    console.log('step 4 - return result');
    dataContainer(newData);
  });

  return dataContainer; // Initially empty array
};

In my opinion, it's better to define the array in your viewModel first and then write to it within the then block by referencing it. You might find it helpful to use a class/instance based approach so you can refer to the dataContainer using this... But ultimately, it comes down to personal preference.

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 I efficiently include all css from node_modules in vuejs?

For my Vue.js app built with the webpack template and vuetify, I am starting by importing the vuetify css in my App.vue. <style> @import '../node_modules/vuetify/dist/vuetify.min.css' </style> I'm wondering if this is the c ...

Validation errors are returned by express-validator duplicated

I am working on validating the request object using Express-Validator. Suppose I have two routes: a GET /users/:id route (fetchUserById) and a POST /users route (createUser). this.router = express.Router(); this.router.route('/').post(this.userR ...

Top method for organizing an array based on an object's property and displaying the outcome

I encountered a problem for which I couldn't find an immediate solution. I have an array of objects representing products, with each product having a category property. My goal is to group these products by their categories. After some trial and error ...

What is the process for displaying a Bootstrap Icon on a webpage?

I recently started using Bootstrap and I'm in the process of creating a login screen for my app. I want to incorporate MDBIcons for Google, Twitter, and Facebook. I referred to the documentation provided at However, upon previewing my webpage, I enco ...

Unable to access a variable declared within an anonymous function in JavaScript beyond its scope

My setup is straightforward: let genres; $.get('/api/genres', '', function (response) { genres = response.data }, 'json'); $("#genre").tagit({ availableTags: genres //this isn't functioning as expected }); I&apo ...

When attempting to utilize an Angular component in an AngularJS environment, the component may fail to display properly

I have followed various articles and posts to set up the basic configuration for bootstrapping an AngularJS app in preparation for migration. import { DoBootstrap, NgModule } from '@angular/core'; import { BrowserModule } from '@angular/plat ...

Tips on showcasing Java map information obtained from the backend on an Angular/Typescript interface

I have a 'detailsMap : any' variable from the backend that contains multiple rows in the format (key1,key2). I need to display this data in the UI using TypeScript/Angular2. Please advise on how I can achieve this. key1 : { Name:'ABC' , ...

Refreshing directive function following a POST request with Angular JS

I am currently working on an open-source application that utilizes AngularJS for the frontend. The app has a unique structure where it manipulates the DOM by deleting and adding content for security reasons. However, I have encountered a challenge that I a ...

Breaking down nested dictionary into separate columns within a pandas DataFrame

I am facing a challenge with two data frames that have a column named 'author' with different formats: df1 author {'name': 'Reuters Editorial', 'url': None} df2 Authors {:name ""Arjun Sidharth"", ...

When attempting to open a popup form by clicking a button, the code fails to function on IE6

Everything seems to be running smoothly on Firefox, however I am encountering issues with Internet Explorer 6. Here is a snippet of the problematic code: document.getElementById('layout').style.opacity = .7 document.getElementById('layout&a ...

Displaying HTML content from a Vuejs response within a Dialog box

After receiving a response from the server via a REST request in HTML format, I have saved it in a data:[] variable. When I log this data on the console, it appears as raw HTML code. This reply is currently stored as a String, and my challenge now is to co ...

Tips for implementing pagination in a datatable using Element UI:

I am puzzled by the fact that the el-table component does not have built-in pagination functionality. While there is a separate pagination component available, there is no clear explanation on how to integrate it with an el-table. I am struggling to under ...

Extracting Data from JSON Using Vue.js

I am facing an issue with extracting data from a JSON file using Vue.js. Below is the HTML and JSON data along with the script. Any help would be appreciated. <!DOCTYPE html> <html> <head> <title>Vu ...

Struggling to make changes to a Styled Component in a React application

In a certain file, I have a BaseComponent composed of various other components and being exported. The top level of the BaseComponent contains a wrapper responsible for managing margins. When I export it and attempt to override some styles with: //other fi ...

Using jQuery ajax links may either be effective or ineffective, depending on the scenario. At times

Can someone please assist me in understanding why an ajax link may or may not work when clicked? It seems to function intermittently. window.onload = function(){ function getXmlHttp(){ ...... // simply ajax } var contentContainer = ...

Creating a new service in Vue is a simple process that allows you to utilize powerful tools like this.$t and this.$alert

I've created a service file named message.vue <script> export default { methods:{ alert(msg,title){ this.$alertify.alert( title,msg); } } } </script> Here's how I use it: import me ...

"Internet Explorer naturally selects the submit button when users press the enter key to submit a

In my current application, I have implemented a form with a hidden button to address issues with the numeric keyboard on Android. Essentially, pressing enter or focusing on the invisible button will trigger form submission. Pressing enter works fine in Ch ...

Tips for creating a conditional confirm dialog box in Asp.net using JQuery/Javascript

I have some jQuery and traditional JavaScript mixed together to validate a textbox on my ASP sample page. There is a button, a textbox, and a button_click event in the code behind. When the button is clicked, I want to show an alert if the textbox is empty ...

User controls and the window.onload event handler

Is there a way for ASP.NET ASCX controls to have their own individual client-side load event, similar to a window.onload, allowing me to hide loading divs and display content divs once the HTTP transfer is finished? I'm struggling with implementing l ...

Just starting out with coding and feeling a bit lost - Echo

Forgive my lack of understanding. This is my first time delving into the world of coding and it all seems a bit confusing and overwhelming. I'm trying to keep it simple by following a guide to build something for Amazon Echo. I've reached Step 2 ...