Observable Knockout Dependency

I found an interesting example on the KnockoutJS site () and I want to implement something similar.

My goal is to check if certain values are available on the client side when a category is selected. If they are not, then I need to fetch them from the server. Unlike the example provided, where the products are already on the client side, in my case I need to first check on the client and only go to the server if the data does not exist.

Can anyone provide me with an example or offer any tips on how to achieve this?

Thank you in advance!

Here is the code snippet I have tried (JavaScript):

function getJsonObject(value) {
            return $.parseJSON(value.replace(/"/ig, '"'));
        }

        var sg = getJsonObject('@ViewBag.SchoolGroups');
        var temp = {
            schoolGroups: sg,
            schoolsBySchoolGroup: undefined,
            getSchools: function (schoolGroupId) {
                alert(schoolGroupId);
                if (this.schoolsBySchoolGroup === undefined) {

                    //get data from server
                }
                else {

                    //verify if data exists

                    //if not, retrieve from server
                }

                return "something...";
            }
        };    

$(document).ready(function () {

                var CartLine = function () {
                    var self = this;
                    self.schoolGroup = ko.observable(sg[0].Id);
                    self.school = ko.observable();

                    // Whenever the category changes, reset the product selection
                    self.schoolGroup.subscribe(function () {
                        self.school(undefined);
                    });
                };

                var Cart = function () {
                    // Stores an array of lines, and from these, can work out the grandTotal
                    var self = this;
                    self.lines = ko.observableArray([new CartLine()]); // Put one line in by default

                    // Operations
                    self.addLine = function () { self.lines.push(new CartLine()); };
                    self.removeLine = function (line) { self.lines.remove(line) };
                };

                ko.applyBindings(new Cart());
            });

HTML code:

 <table>
                        <thead>
                            <tr>
                                <th>Start Date</th>
                                <th>School Group</th>
                                <th>School</th>
                                <th></th>
                            </tr>
                        </thead>
                        <tbody data-bind='foreach: lines'>
                            <tr>
                                <td>
                                    <input class='required datepicker' />
                                </td>
                                <td>
                                    <select data-bind='options: temp.schoolGroups, optionsText: "Name", optionsValue: "Id", value: schoolGroup'></select>
                                </td>
                                <td data-bind="with: schoolGroup">
                                    <select data-bind='options: temp.getSchools($parent.schoolGroup.Id), optionsText: "Name", optionsValue: "Id", optionsCaption: "Select...", value: $parent.school'></select>
                                </td>
                                <td>
                                    <a href='#' class="none" data-bind='click: $parent.removeLine'><i class="icon-remove"></i></a>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                    <a href='#' class="none" data-bind='click: $root.addLine'><i class="icon-plus"></i></a>

I attempted using $parent and $data without success...

Answer №1

Using a JSFiddle, I have created a simulation where server calls are mimicked by time delays. When a category is selected, the subcategories are retrieved from the server and stored within the category item. As a result, if the same category is reselected, the subcategories are not fetched from the server again.

var Category = function (title) {
    var self = this;
    self.subcategories = ko.observableArray(null);
    self.title = title;
};

var ViewModel = function (categories) {
    var self = this;
    self.selectedCategory = ko.observable();
    self.availableCategories = categories;

    self.selectedCategory.subscribe(function (item) {
        if (item.subcategories()) {
            self.availableSubcategories(item.subs());
        } else {
            serverCall(item.title, function (subCats) {
                item.subcategories(subCats);
                self.availableSubcategories(subCats);
            });
        }
    });

    self.selectedSubcategory = ko.observable();
    self.availableSubcategories = ko.observableArray();
}

var viewModel = new ViewModel([new Category('Cat1'), new Category('Cat2'), new Category('Cat3')]);

ko.applyBindings(viewModel);

var serverCall = function (category, callback) {

    setTimeout(function () {
        var array = [];
        for (var index = 0; index < 5 ; index++) {
            array[index] = category + ' - ' + index;
        }
        alert('Server Call');
        callback(array);
    }, 1000)

};

I trust that this explanation is clear and beneficial to you.

Answer №2

Performing the following actions within the subscribe handler is recommended. Below is a basic example in pseudo code:

self.category.subscribe(function () {
  if (values exist on client)
    self.product(values from client);

  else
    // initiate ajax call to retrieve values
});

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

I'm looking to design a navbar similar to the one in the provided link, and I'd like it to appear when scrolling

I'm struggling to figure out how this particular navbar was created. How can I add a navlist for Videos and make the navbar visible upon scrolling? Are there any resources, articles, or hints to help me get started with this? LINK - ...

What is the best way to stop webpack from generating typescript errors for modules that are not being used?

The directory structure is set up as follows: └── src ├── tsconfig.json ├── core │ ├── [...].ts └── ui ├── [...].tsx └── tsconfig.json Within the frontend, I am importing a limi ...

Problem with Gulp-Watch Functionality on Windows 7 - Node.js, NPM, and Gulp All Up and Running Fine

As someone who is new to the world of Node.js, NPM, and other modern tools designed to improve productivity and workflow, I find myself faced with some challenges. Below are the specifications: Node version - v8.10.0 Gulp CLI version - 2.0.1 Gulp Loca ...

Angular SPA Routing for .Net Core 2.0

Having recently created a new Angular SPA project using the .Net core 2.0 SPA templates, I find myself facing some challenges as a newcomer to Angular/Typescript and HMR. While most functionalities were working smoothly at first, I noticed a peculiar issu ...

Deploying an Azure Blob Trigger in TypeScript does not initiate the trigger

After successfully testing my Azure function locally, I deployed it only to find that it fails to trigger when a file is uploaded to the video-temp container. { "bindings": [ { "name": "myBlob", "type&qu ...

How to prevent all boxes in jQuery from sliding up at the same time

I am encountering an issue with 36 boxes where, upon hovering over the title, the hidden text below it should slide up. However, all 36 boxes are sliding up simultaneously instead of just the one being hovered over. Below is the script I am currently using ...

Guide on making an NPM package with a web worker integration

Currently, I am in the process of developing an npm package that incorporates a web worker with type module. The issue arises when I try to link this package to a React application for testing purposes since the application cannot locate the worker.js file ...

Updating an object property within an array in Angular Typescript does not reflect changes in the view

I am currently delving into Typescript and Angular, and I have encountered an issue where my view does not update when I try to modify a value in an array that is assigned to an object I defined. I have a feeling that it might be related to the context b ...

What is the best method to obtain the following id for an image?

Whenever I hover over the li with the number 3, I am getting the wrong number for the next id in the img tag. The first time, I get next id = 4 which is incorrect. But on the second hover, I get next id = 0 which is what I actually need. How can I correctl ...

Is JSON Compatible with the Switch Statement?

Could someone help me with creating a switch statement in JSON? {"Errors":{"key1":"afkafk"},"IsValid":false,"SuccessMessage":""} I attempted to use: switch(response) { case response.Errors.key1: alert('test'); default: } However, t ...

watchWebpack is compiling all the files

As per the webpack documentation on watching files webpack can keep an eye on files and recompile them whenever there are changes. My understanding is that this implies webpack will only compile the files that have been modified. I have a configuratio ...

Invalid for the purpose of storage

Encountering the following error message: The dollar ($) prefixed field '$size' in 'analytics.visits.amounts..$size' is not valid for storage. return Manager.updateMany({}, { $push: { & ...

Automatically switch to dark mode at specified times: A simple guide

Here is the current method for toggling themes: let themeToggler = document.getElementById('theme-toggler'); themeToggler.onclick = () => { themeToggler.classList.toggle('fa-sun'); if (themeToggler.classList.contains('f ...

Employing the 'this' keyword for iterating over a jQuery selector

Having an issue with a jQuery code that logs the values of input fields on button click: Tried using forEach method on inputs but getting an error saying it's not a function. Why is this happening? $("#submit").click(e => { e.preventDefault(); ...

The execution of the code may encounter errors initially, but it generally runs without any issues on subsequent attempts

I recently developed a piece of code to ascertain whether a value in the database is null or not. Here's the snippet: var table; var active = false; function CheckActive(table){ this.table = "table" + table + ""; var db = window.openDatabas ...

Trick to enable editing in Bootstrap Select Combobox

Is there a way for users to add their own options to bootstrap-select? Greetings! I have spent some time searching for a straightforward solution that is compatible with Bootstrap 4 styling. Despite exploring various suggestions, as well as unresolved thr ...

Typescript encountering onClick function error during the build process

My current challenge involves creating a submit function for a button in my application. However, when I attempt to build the project, I encounter a typing error that is perplexing me. Despite trying various methods, I am unable to decipher how to resolve ...

Leveraging jQuery to interact with MySQL database in PHP Laravel framework

I seem to have hit a roadblock with my database, which is quite intricate. Here's the breakdown of the tables used for the questions: product - contains product details such as shoes productattribute - houses different variations of products like bl ...

Exploring data visualization within a JSX Component

I am attempting to dynamically render a Card component that is mapped from an array of objects. However, I am encountering an "unexpected token error" and the URL is not rendering as expected. The goal is to display five cards based on the data within the ...

Generating a Random Number Within a Specified Range

function generateRandomNumberBetween(start, stop) { var low = Math.ceil(low); var high = Math.floor(high); return Math.floor(Math.random() * (high - low + 1)) + min; } function testRandomNumberGeneration() { var start = parseInt(prompt("Enter low ...