Monitoring and tracking every alteration to a property in a designated observable area

I'm currently working with KnockoutJS version 3.4.

In TypeScript, my view model is structured as follows:

export class ItemsViewModel {
    public currentItem: KnockoutObservable<ItemViewModel>;
    public items: KnockoutObservableArray<KnockoutObservable<ItemViewModel>>;
    /* snip */
}

The ItemViewModel object consists of multiple observable properties such as Id, Name, and Description.

I am looking to subscribe to specific property changes within the currentItem. Using currentItem.subscribe allows me to monitor changes in the overall value of the currentItem observable, but I need a way to identify when individual properties are modified within that item. The other question referenced as a duplicate only tracks changes at the object level, whereas I require detection at the property level.

What would be the most efficient approach to achieve this?

Edit: Taking into account the feedback and associated question, it does not provide details on which property was altered. Therefore, I have made amendments to clarify this inquiry.

Answer №1

To pinpoint the modified property, a more specific approach is necessary. This can be achieved by adding an extender to each property that requires tracking. The extender should accept a subscribable at the view-model level to notify and the name of the extended property. (unfortunately JavaScript lacks reflection for this purpose)

ko.extenders.trackChange = function (target, options) {
    target.subscribe(function (newValue) {
        if (ko.isSubscribable(options.notifier)) options.notifier.notifySubscribers(options.propertyName);
    });
    return target;
};

Subsequently, in your view-model, include the subscribable and subscription.

self.propertyChanged = new ko.subscribable();
self.propertyChanged.subscribe(function(propertyName){
  console.log(propertyName + " was updated");
});

Lastly, apply the extender to your properties.

self.property1 = ko.observable(0).extend({trackChange: { propertyName: 'property1', notifier: self.propertyChanged }});
self.property2 = ko.observable(0).extend({trackChange: { propertyName: 'property2', notifier: self.propertyChanged }});
self.property3 = ko.observable(0).extend({trackChange: { propertyName: 'property3', notifier: self.propertyChanged }});

If you wish to apply this to every property automatically, you could use a loop within the view-model:

self.property1 = ko.observable();
self.property2 = ko.observable();
self.property3 = ko.observable();

for (key in self) {
    if (self.hasOwnProperty(key) && ko.isObservable(self[key])) {
        self[key].extend({trackChange: { propertyName: key, notifier: self.propertyChanged }})
    }
}

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

Implementing the 'keepAlive' feature in Axios with NodeJS

I've scoured through numerous sources of documentation, Stack Overflow threads, and various blog posts but I'm still unable to make the 'keepAlive' functionality work. What could I be overlooking? Here's my server setup: import ex ...

The Power of Asynchronous Programming with Node.js and Typescript's Async

I need to obtain an authentication token from an API and then save that token for use in future API calls. This code snippet is used to fetch the token: const getToken = async (): Promise<string | void> => { const response = await fetch(&apos ...

Bring in an Angular Component into a different Component by stating the name of the component as an input parameter

In my project, I am looking to develop an angle component made up of multiple sub-components. The end goal is to construct a versatile tree component with nodes that cater to different data types. Each data type in the tree component will import specific s ...

Ensure that the default boolean value is set to false rather than being left as undefined

I have a specific type definition in my code: export type ItemResponse = { .... addedManually: boolean; .... } Whenever I parse a JSON response into this type, I encounter an issue: const response = await fetch( `https://api.com` ); con ...

Cancel all uncompleted axios requests and start fresh

I am currently utilizing the axios library for handling API requests. I find myself in a situation where I need to cancel all ongoing or pending requests and initiate new ones using a different API. I have attempted the following code: async getOldRespon ...

Global Enum in Typescript that is Optimized for Inlining during Compilation

I'm facing a challenge with an enum that is widely used in my project. Having to import it into every file is becoming cumbersome. Is there a way to define the enum in the .d.ts file so that it automatically gets included when compiled to Javascript? ...

Error: The data received from the Axios GET request cannot be assigned to the parameter type of SetState

Currently I am in the process of building my initial TypeScript application after transitioning from a JavaScript background. While I am still adjusting to the concept of declaring types, there is a specific issue I am encountering at the moment. The sni ...

Issue encountered when trying to bring in a component from a different module

I am attempting to import the 'OpenDialogContentComponent' component from Module A into Module B, however I am encountering this error: 'Cannot determine the module for class OpenDialogContentComponent in C:/Users/jitdagar/Desktop/TDP/pwt-u ...

When working with formControlName in Angular Material 2, the placeholder may overlap the entered value

After updating my application with angular-cli to angular/material (2.0.0-beta.11) and angular (4.4.4), I noticed that every placeholder in the material input fields overlaps the value when provided with formControlName in reactive forms. However, when usi ...

Outdated compiler module in the latest version of Angular (v13)

After upgrading to Angular 13, I'm starting to notice deprecations in the usual compiler tools used for instantiating an NgModule. Below is my go-to code snippet for loading a module: container: ViewContainerRef const mod = this.compiler.compi ...

Tips on preventing the duplication of component instances in your project

Check out the plunker link to see that the child component "Loader" is being loaded multiple times every time the button is clicked. How can I prevent creating multiple instances of the same component? I want the new instance to replace the existing one wh ...

Issue with knockout view - unable to remove item from view after deletion

I'm facing an issue with my code that deletes an exam from a list of exams on a page, but the deleted exam still shows up until the page is manually refreshed. This pattern works correctly on other pages, so I don't understand why it's not w ...

Display a loading indicator with the shortest possible delay whenever utilizing the React Router v6 Link functionality

Integrate React and Router v6 App.tsx: const Page1 = lazy(() => pMinDelay(import('./views/Page1'), 500)) const Page2 = lazy(() => pMinDelay(import('./views/Page2'), 500)) return ( <Suspense fallback={<Loading/>}gt ...

Unable to loop through the Array

let Users = [ { name: 'John', id: '1', jp: 'USA' }, { name: 'Jane', id: '2', jp: 'Japan' }, ]; export function DisplayUsers(usersList) { return ( <div> {usersList?.map((user ...

Is it possible to globally define a namespace in Typescript?

Seeking a way to make my Input module accessible globally without the need for explicit path definitions. Currently, I have to import it like this: import { Input } from "./Input/Input";. Is there a method to simplify the import statement for modules con ...

Obtain a stream containing a collection of information

Is there a different approach to retrieving an Observable with an Array of ReferenceData arrays? I've been struggling with this issue for a couple of days. Here is my current code: export class ReferenceData { id: number; caption: string; const ...

HostListener in Angular 17 for BeforeUnloadEvent

I am currently working on an Angular 17 application and I have come across the following block of code: @HostListener("window:beforeunload", ["$event"]) onTabClose($event: BeforeUnloadEvent) { $event.preventDefault(); $even ...

Managing errors when dealing with Observables that are being replayed and have a long lifespan

StackBlitz: https://stackblitz.com/edit/angular-ivy-s8mzka I've developed an Angular template that utilizes the `async` pipe to subscribe to an Observable. This Observable is generated by: Subscription to an NgRx Store Selector (which provides sele ...

Glitch causing incorrect images to appear while scrolling through FlashList

Currently, I am using the FlashList to showcase a list of items (avatars and titles). However, as I scroll through the list, incorrect images for the items are being displayed in a mixed-up manner. Based on the explanation provided in the documentation, t ...

Utilizing the onBlur event to control focus within a React element

In the React component I'm working on, I have implemented an onBlur event handler. The logic inside this handler is supposed to return focus back to the target element. This code is written in TypeScript. emailBlur(e: React.FocusEvent<HTMLInputEle ...