Arrays of objects nested within knockout arrays

As a newcomer to knockout, I am excited to dive into it head first. Here's my issue: I'm attempting to access a list (array) of objects within another list of objects (array).

For example: (to keep it simple)

Teacher -> Students

  1. Teacher #1

    • Student 1
    • Student 2
    • Student 3
  2. Teacher #2

    • Student 1
    • Student 2
    • Student 3
  3. Teacher #3

    • Student 1
    • Student 2
    • Student 3

While I've successfully displayed the list of all teachers, when it comes to displaying the list of students, the last node (Teacher #3) shows all the students from Teachers (#1, #2, and #3); while Teacher #1 and #2 are blank.

var ViewModel = {
       Teachers: ko.observableArray([])
}

function LoadTeachers(....) //Here Teacher list is loaded successfully.>

ko.applyBindings(ViewModel);


function teacher(T){
 this.TeacherID:ko.observable(T.TeacherID);
 this.TeacherName: ko.observable(T.TeacherName);

 this.StudentArray = ko.observableArray([]);

 function student(s){
    this.StudentID=ko.observable(s.StudentID);
    this.Name = ko.observable(s.s.Name);
 }

$.getJson('...');  // here is where Student array is loaded. 

}

then I would have in my view page:

foreach: Teacher  
foreach: Student

Drawing on my C# knowledge and applying it to knockout, I suspect the issue lies in declaring the Student Array inside the teacher object, since each student belongs to a specific teacher. In C#, this is how I would approach it.

Is there a way to make this coding work? I hope so!

Thank you in advance

Answer №1

For now, I am setting aside the Knockout mapping plugin (which has its merits but lacks in certain areas). This decision is aimed at presenting you with a straightforward solution. While you did encounter some peculiarities with knockout, the main issue was actually related to a closure mistake. The crucial part of the code lies within var newTeacher = .... It is vital to have this within the nested ajax closure. Below is the updated code along with a link to the functional fiddle:

$(document).ready(function(){
    var ViewModel = {
        Teachers: ko.observableArray([])
    };

    // Using fake data instead of actual ajax calls for demonstration purposes
    var fakeTeacherData = [{TeacherID: 1, TeacherName: 'Dan'}, {TeacherID: 2, TeacherName: 'Marian'}];
    var fakeStudentData = [{StudentID: 1, Name: 'Student 1'}, {StudentID: 2, Name: 'Student 2'}];

    $.get('/echo/json', function(teacherData){
        // Actual data usage will replace this section
        ko.utils.arrayForEach(fakeTeacherData, function(T){
            var newTeacher = new teacher(T);
            ViewModel.Teachers.push(newTeacher);

            $.get('/echo/json', function(studentData){
                // Actual data usage will replace this section   
                ko.utils.arrayForEach(fakeStudentData, function(S){
                    newTeacher.Students.push(new student(S));
                });
            });
        });
    });
    ko.applyBindings(ViewModel);
});

function teacher(T){
    this.TeacherID = ko.observable(T.TeacherID);
    this.TeacherName = ko.observable(T.TeacherName);
    this.Students = ko.observableArray([]);
}

function student(S){
    this.StudentID = ko.observable(S.StudentID);
    this.Name = ko.observable(S.Name);
}

http://jsfiddle.net/kXQxA/

Answer №2

To showcase students grouped by teacher, you can try a setup similar to this example.

Teacher = function (data) {
    var self = this;
    self.Id = ko.observable(data.Id || 0);
    self.Name = ko.observable(data.Name || '');
    // Refer to JSFiddle for mapping details
    self.Students = ko.mapping.fromJS(data.Students, StudentMapping);
    return self;
};

Student = function (data) {
    var self = this;
    self.Id = ko.observable(data.Id || 0);
    self.Name = ko.observable(data.Name || '');
    return self;
};

StaffViewModel = function (data) {
    var self = this;
    // Check JSFiddle for mapping reference
    ko.mapping.fromJS(data, StaffMapping, self);
    return self;
};

I am utilizing the original Knockout mapping plugin in this scenario, but feel free to explore the viewmodel plugin as well.

If your preference is to display students and teachers separately, it might be better not to make students observable properties of 'Teacher'. Instead, you can include code within the ViewModel constructor to generate a distinct list of students. The mapping plugin will still provide assistance here, especially with the 'key' function to avoid duplicates.

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

After successful sign-in, users will be redirected to the

After mainly working on mobile development, I am now diving into web development. I am currently utilizing firebase.auth() to sign in a user and I'm struggling with how to handle page redirection within my JavaScript/node application. What is the pro ...

Sending both an array and an image via Ajax in a single request

I need to send both JSON and file data to my PHP backend using an ajax call. Here is my current ajax call: $.ajax({ type: 'POST', dataType: 'json', data: jsonData, url: 'xxx.php', cache: false, suc ...

Leveraging the socket.io and express modules independently of npm

I am currently developing a project for an embedded Linux system using busybox created with buildroot. I'm intrigued by the idea of utilizing node.js modules such as socket.io and express without needing to depend on the installation or execution of n ...

The information from the Ajax request does not get properly delivered to the $_POST array

Apologies if this question has been raised before, but none of the responses to other inquiries have provided a solution to my issue. I am currently developing a user login system that utilizes an .ajax() call to my login.php file for user authentication. ...

Handling every promise in an array simultaneously

I am facing a problem with my array inside Promise.all. When I try to execute a function for the last iteration of forEach loop, I notice that my count_answers variable is only being set for the last object. This can be seen in the log output; the count_an ...

Verify the middleware is connected to the express endpoint during the unit test

How can I verify that the middleware is properly attached to the route in my unit test below? The server .. var express = require('express'); var http = require('http'); var app = express(); var server = http.createServer(app); var P ...

Utilizing JQuery to merge variable identifiers

Imagine a scenario where the variables are structured this way: localStorage.var1a = 0; localStorage.varnum = 1000; Now, consider the following code snippet: for(x = 1; x < localStorage.varnum; x++){ if(localStorage.var.x.a > 0){ localStora ...

Connect ngOptions to an array beyond the current scope

Can the ngOptions be bound to a value that is not within the $scope? I have enums that will be generated as JavaScript code. These enums are not currently part of "the angular domain", but I want to bind an ngOptions to one of the arrays without manually ...

What are the steps to clipping a canvas using CSS clip-path?

When it comes to clipping a canvas, there are multiple methods that can be used. One way is to create a path with getContext('2d') and set globalCompositeOperation. Another method involves using -webkit-clip-path or clip-path, though the latter m ...

Tips on how to showcase particular keys from json information in React

Here is a sample of Json data that I have: [ { "serial_number": "test1", "added_at": "2021-02-05T18:58:43.382943Z", "ser_mod": [ { "added_at": "2021-02-06T02: ...

Creating a combination of associative keys and numbers within an array using JavaScript

To summarize, my question starts below: I have simply read a JSON file with the following contents: [{"FirstCategory":"Bath","SecondCategory":"Bath Accessories","ThirdCategory":""}, {"FirstCategory":"Bath","SecondCategory":"Faucets","ThirdCategory":""}, ...

What is the best way to monitor changes in objects within a JavaScript array?

Currently, I am in the process of developing a Todo application using electron and Vue.js. In my project, there is an array of objects called items. Each object follows this format: {id: <Number>, item: <String>, complete: <Boolean>, ...

Understanding the Typescript Type for a JSON Schema Object

When working with JSON-schema objects in typescript, is there a specific type that should be associated with them? I currently have a method within my class that validates whether its members adhere to the dynamic json schema schema. This is how I am doing ...

Guide to outputting a JSON array in Struts 2

Below is the code for my Struts action: @Action("/trylogin") @ParentPackage("json-default") @Result(type = "json", params = { "includeProperties", "msg, productsList" }) public class Login extends ActionSupport { private static final long serialVersio ...

Guide on how to design a schema in Mongoose for uploading arrays of objects in MongoDB

[ const arrayOfObjectsSchema = new Schema({ array: [ { title: { type: String, required: true, }, desc: { type: String, required: true, }, img: { type: String, required: tru ...

Retrieving the ID of a clicked div in jQuery

I am working with an HTML structure that looks like this: <div class='mydiv' id='89'>hello</div> <div class='mydiv' id='123'>hihihi</div> Currently, my jQuery script is as follows: $(&apo ...

In what cases does modelObject.save() update a database document aside from when the modelObject was retrieved from the database?

Let's consider an example where we have a User model defined with a specific schema: var UserSchema = new Schema({ username: String, email: String } mongoose.model('User', UserSchema); If we want to update a user using the save me ...

Diminishing sheets in the realm of C# web application development

I have been researching ways to incorporate a fading page function, but I am encountering some issues. I am unsure about the specific code that needs to be included in jquery.js and how to integrate this script into all of my web forms or alternatively int ...

Transforming JSON data into HTML displays only the final <li> element

Please take a moment to review the question provided at the end of this post. I am struggling with understanding why only the last li element from the JSON is being rendered. As a newcomer in this field, any help or guidance would be greatly appreciated! ...

Express router fails to mount

Struggling with my first project using expressjs, I have encountered an issue with a router not properly mounting. My approach involves the app mounting a router object which should then mount a second router object. While the first embedded router mounts ...