Leveraging KnockoutJS and PubSub for seamless updates of observable arrays across multiple views

In my project, I have implemented two modal views - MyModalViewA (parent) and MyModalViewB (child).

The MyModalViewA spawns MyModalViewB as a custom binding, along with an observable array that needs to be updated. Here is what the code looks like:

(function () {

            'use strict';

            var
                window = __webpack_require__(/*! window */ 10),
                _ = __webpack_require__(/*! _ */ 2),
                $ = __webpack_require__(/*! $ */ 12),
                ko = __webpack_require__(/*! ko */ 3),
                key = __webpack_require__(/*! key */ 16),

                Enums = __webpack_require__(/*! Common/Enums */ 4),
                Utils = __webpack_require__(/*! Common/Utils */ 1),

                Links = __webpack_require__(/*! Common/Links */ 13),
                Remote = __webpack_require__(/*! Remote/User/Ajax */ 14),

                kn = __webpack_require__(/*! Knoin/Knoin */ 5),
                AbstractView = __webpack_require__(/*! Knoin/AbstractView */ 11),
                AttachmentModel = __webpack_require__(/*! Model/Attachment */ 86)
            ;

    function MyModalViewA()
    {
       ...some observables...
       //data response which must be updated
       this.rows= ko.observableArray([]);

       this.getResults = Utils.createCommand(this, function() 
       {
         kn.showScreenPopup(__webpack_require__(/*! View/Popup/SearchUsers */ 171),[oData]);
       }
    }

 kn.constructorEnd(this);
}

module.exports = MyModelViewA;

}());

Next, let's look at MyModelViewB:

(function () {

            'use strict';

            var
                window = __webpack_require__(/*! window */ 10),
                _ = __webpack_require__(/*! _ */ 2),
                $ = __webpack_require__(/*! $ */ 12),
                ko = __webpack_require__(/*! ko */ 3),
                key = __webpack_require__(/*! key */ 16),

                Enums = __webpack_require__(/*! Common/Enums */ 4),
                Utils = __webpack_require__(/*! Common/Utils */ 1),

                Links = __webpack_require__(/*! Common/Links */ 13),
                Remote = __webpack_require__(/*! Remote/User/Ajax */ 14),

                kn = __webpack_require__(/*! Knoin/Knoin */ 5),
                AbstractView = __webpack_require__(/*! Knoin/AbstractView */ 11),
                AttachmentModel = __webpack_require__(/*! Model/Attachment */ 86)
  ;

        function MyModalViewB()
        {
           ...some observables...

        this.doSearch = Utils.createCommand(this, function() 
        {
           MyModelViewB.findUsers(userId);
        }

        kn.constructorEnd(this);
        }

        MyModelViewB.findUsers = function (userId)
        {
             //here I'm retrieving rows 
             //and I need to update rows from MyModalViewA
        }


    module.exports = MyModelViewB;

    }());

After referring to a suggestion on synchronizing view models in Knockout, I attempted to use PubSub for updating

this.rows= ko.observableArray([]);
in MyModelViewA.

I added var postbox = ko.observable(); to the constructor variables of MyModelViewA. Then, in MyModelViewA, I included:

   postbox.subscribe(function(newValue) {
        this.rows.push(newValue);
    }, this);

And in MyModelViewB, I added:

this.results = ko.observableArray([]);
this.results.subscribe(function(newValue) {
    postbox.notifySubscribers(newValue);
});

However, both views were not receiving the value of newValue, and MyModelViewA's this.rows was not being updated when hardcoded in MyModelViewB.

At this point, I am unsure if the solution provided in the link above is working correctly.

Edits

I added the following code snippet to the top of my modules bundle:

var postbox = new ko.subscribable();

As the below code was causing an error:

(function($) { $(function() {
    window.postbox = new ko.subscribable();
    });
});

The error message stated: "Cannot read property 'subscribe' of undefined"

Then, in the module for MyModalViewA, I simplified the version based on PFX answer:

    postbox.subscribe(function(newValue) {
            self.myTest(newValue);

            console.log('New value: ' + newValue);
        }, null, "NewRowAvailable"
    );

And in the module for MyModalViewB, under MyModelViewB.findUsers, I added:

var newRow = "testing123";
postbox.notifySubscribers(newRow, "NewRowAvailable");

Upon debugging the code, it was observed that postbox was defined as Object {NewValueAvailable: }, but notifySubscribers was not updating the subscribable.

Any insights or suggestions on how to resolve this issue?

Answer №1

Ensure that the postbox instance is singular and shared between both viewmodels, following the specific signatures for the notifySubscribers and subscribe methods detailed below.

notifySubscribers(eventData, eventName); 

subscribe(function(eventData) { ... }, null, eventName);

Presented below is a simplified depiction of your desired outcome.
In this example, only one search result is being passed, but it could also be multiple results through something like an array.

var postbox = ko.observable();

function MyModalViewA()
{
    var _self = this;
    _self.rows = ko.observableArray([
        { label: "foo" },
        { label: "bar" }    
        ]);
    
    postbox.subscribe(function(newValue) {         
          _self.rows.push(newValue);
      }, null, "PFX.NewRowAvailable"
      );
};

function MyModalViewB()
{
    var _self = this;
    
    _self.search = function() {
    
        var newRow = { "label" : "baz" };
        postbox.notifySubscribers(newRow, "PFX.NewRowAvailable");      
    };
};

var vma = new MyModalViewA();
ko.applyBindings(vma, $("#vma").get(0));

var vmb = new MyModalViewB();
ko.applyBindings(vmb, $("#vmb").get(0));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<div id="vma">
    <h3>ViewModel A</h3>
    <ol data-bind="foreach: rows">
        <li data-bind="text: label"></li>
    </ol>
</div>

<hr />

<div id="vmb">    
    <h3>ViewModel B</h3>
    <button data-bind="click: search">search</button>
</div>

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

There was a problem fetching Binary data through the AMQP receiver

Currently, I am attempting to retrieve messages using a nodejs + amqp receiver. In my observation, any binary data exceeding 7f are displayed as ef bf bd. var messageHandler = function (myIdx, msg) { var data = new Buffer(msg.body) console.log(dat ...

Array of Checkboxes

Seeking assistance with a coding dilemma. Here is the existing code snippet: <section> <span class="tags"></span> <label for="shoes">Shoes</label> <input type="checkbox" id="shoes"> <label for="jeans">Je ...

Enhance your AJAX calls with jQuery by confidently specifying the data type of successful responses using TypeScript

In our development process, we implement TypeScript for type hinting in our JavaScript code. Type hinting is utilized for Ajax calls as well to define the response data format within the success callback. This exemplifies how it could be structured: inter ...

Customizing the Material UI theme colors using Typescript

I have created my own unique theme and now I am attempting to assign one of the custom colors I defined to a button. However, when I try to set it as: color={theme.pallete.lightGrey} I run into this error message: No overload matches this call Overload 1 ...

Inheritance from WebElement in WebdriverIO: A Beginner's Guide

I am seeking a solution to extend the functionality of the WebElement object returned by webdriverio, without resorting to monkey-patching and with TypeScript type support for autocompletion. Is it possible to achieve this in any way? class CustomCheckb ...

When I apply properties in JavaScript, I find that I am unable to utilize the CSS "hover" feature

For a personal project I am currently working on, I decided to experiment with setting background colors using Javascript. However, I have encountered an issue where my CSS code that changes the hover property does not seem to work after implementing the J ...

Ways to ensure that long is always 4 bytes in size

Currently, I am facing an issue with the compilation of my project. After compiling, I see that the size of long int is 8 bytes, whereas the size of int is 4 bytes. However, I actually need the size of long int to be 4 bytes. Is there a possible solution ...

Utilizing the Jquery hover feature to reveal or conceal an element

My Hover function is designed to display and hide sub menus when a person hovers on them. The issue I'm facing is that the menu disappears when I move the mouse down towards it. Can someone help me identify what I am doing wrong here? ...

npm: Import a package from a GitHub repository that does not belong to me

I have encountered a package that I need for my project, but it is not available in npm. I am considering the option of uploading the package to npm myself. However, I am unsure if this is ethically or legally acceptable. What is your opinion on this mat ...

Enhance the efficiency of DataTable by optimizing cell class modifications

I have been very pleased with the performance of jquery DataTables, but I have encountered a situation where I need to optimize it further. Specifically, I am updating the class of a cell based on its data. Currently, I am achieving this by using the ren ...

Various Utilizations through a Single Alexa Skill

In my skill SkillIntent, when asked about a specific game, it provides the description of that skill. Now, I want it to also inform WHO has that Skill when asked differently. Below is the code snippet: 'use strict'; var AlexaSkill = require(&a ...

Communicating between PHP chat client and server

Currently, I am developing a basic PHP web chat application that interacts with a MySQL database. The communication is facilitated through AJAX requests - when a user posts a message, it gets saved in the database. function sendData(){ var textData = $(& ...

Trying to follow a guide, but struggling to identify the error in my JavaScript syntax

I'm attempting to follow an older tutorial to change all references of the word "cão" on a page to "gato". These instances are contained within spans, and I'm using the getElementsByTagName method in my script. However, when trying to cycle thro ...

Looping Through RxJS to Generate Observables

I am facing the challenge of creating Observables in a loop and waiting for all of them to be finished. for (let slaveslot of this.fromBusDeletedSlaveslots) { this.patchSlave({ Id: slaveslot.Id, ...

Discover the process of selecting an item from a list and viewing it on a separate page with the help of AngularJS and Ionic technology

I am struggling with creating a list of items that, when clicked, should take me to the corresponding post. Despite trying to use ng-click in the header, I suspect there is an issue with the route not functioning properly. As part of my testing process, I ...

What is the best way to choose distinct items from a Promise<Array[]> in Angular 2/4?

Providing some context, I am working with an API that fetches information about a competition including links to matches, and each match has links to the teams involved. My current goal is to create a standings table based on the matches of the competitio ...

The onProgress event of the XMLHttpRequest is triggered exclusively upon completion of the file upload

I have a situation with my AJAX code where the file upload progress is not being accurately tracked. The file uploads correctly to the server (node express), but the onProgress event is only triggered at the end of the upload when all bytes are downloaded, ...

The ReCaptcha and AJAX Integration

I am attempting to display the ReCaptcha image using its AJAX API. I have been following the instructions from this documentation and observing the behavior of this demo. Despite my efforts, I am still unable to create a functional fiddle. I have added jsf ...

Using socket.io and express for real-time communication with WebSockets

I'm currently working on implementing socket.io with express and I utilized the express generator. However, I am facing an issue where I cannot see any logs in the console. Prior to writing this, I followed the highly upvoted solution provided by G ...

There was a failure to retrieve any data when trying to send an ajax request to

When attempting to send JSON data to my PHP, I am not receiving any response when accessing it in my PHP code. Below is the Ajax request being made: var project = {project:"A"}; var dataPost = JSON.stringify(project); $.ajax({ url: 'fetchDate.p ...