What are the steps to creating an Observable class?

I am working with a class that includes the following properties:

export class Model {
   public id: number;
   public name: string;
}

Is there a way to make this class observable, so that changes in its properties can be listened to?

I'm hoping for something similar to this:

let m = new Model();
m.id = 10;

To listen for changes:

m.pipe(map() => m.id);

Answer №1

Check out this straightforward illustration.

https://example.com/plain-sample

import { Component, OnInit, VERSION } from '@angular/core';
import {BehaviorSubject} from 'rxjs';


@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
model: Model;

  ngOnInit() {
    this.model.id$.subscribe(newId => {
      // implement a specific action here.
    });
  }
}
export class Model {
  // @ts-ignore
  private readonly _id = new BehaviorSubject<number>();
  readonly id$ = this._id.asObservable();
  // @ts-ignore
  private readonly _name = new BehaviorSubject<string>();
  readonly name$ = this._name.asObservable();

  get id(): number {
    return this._id.getValue();
  }

  set id(val) {
    this._id.next(val);
  }

  get name(): number {
    return this._name.getValue();
  }

  set name(val) {
    this._name.next(val);
  }
}

Answer №2

To enhance the functionality of this code, I suggest incorporating it into the constructor. Avoid declaring subjects within the class as they can be challenging to manage automatically.

Instead of injecting subjects directly, consider using a callback for a simpler alternative.

In the example test class provided below, each property allows for a callback to be injected. The respective callback is triggered in the property setters when the value changes.

export class MyClass {
  private _id: number;  
  private _name: string;

  constructor(private callback?: {
    id?: () => void,
    name?: () => void
  }) {}

  get id(): number { 
    return this._id;
  }

  set id(value: number) {
    if (value === this._id) {
      return;
    }

    this._id = value;

    if (this.callback && this.callback.id) {
      this.callback.id();
    }
  }

  get name(): string {
    return this._name;
  }

  set name(value: string) {
    if (value === this._name) {
      return;
    }

    this._name = value;

    if (this.callback && this.callback.name) {
      this.callback.name();
    }
  }
}

Using this code from elsewhere is straightforward.

myClass: MyClass = new MyClass({
  id: () => this.onIdChange()
});

ngOnInit() {
  this.myClass.id = 10;   
  this.myClass.name = 'Default';
}

private onIdChange() {
  console.log(`id changed to ${this.myClass.id}`);
}

If desired, you could modify this to utilize subjects. In that case, the calling code would need to handle cleaning up the subjects appropriately.

DEMO: https://stackblitz.com/edit/angular-ivy-hgxkc3

Answer №3

Incorporate getters and setters for the attributes of your class, implement emitters within it, and then link listeners externally to respond when those emitters are triggered

Answer №4

Initializing a new model instance with id set to 10:

let model = new Model();
model.id = 10;

Creating an observable of the model instance:
const model$ = of(model);

Mapping over the observable to extract the id property:
model$.pipe(map()=> model.id);

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

Transforming TimeZone Date Object without Altering Time

I am looking to change the time zone of a date from one timezone to another. For example: "Sun May 01 2019 00:00:00 GMT+0530 (India Standard Time)" is the current date object. I want to convert this date based on a specific timeZone offset, let's say ...

What is the best way to incorporate vertical scrolling into a React material table?

I'm having trouble getting vertical scroll to work with my material table in React Typescript. Horizontal scroll is functioning properly for large data, but I'm stuck on implementing the vertical scroll. Here's my code: {isLoading ? ...

Unable to confirm the version of Angular

I am currently using node version 10.14.1 and npm version 6.4.1 with angular version 7.0.3 installed. However, when I try to check the angular version by running the ng --version command, I encounter an error message in the command prompt. C:\Users&b ...

Angular-oauth2-oidc does not successfully retrieve the access token when using OAuth2 and SSO

Here's an issue I'm facing: I've been attempting to integrate SSO and OAuth2 flow using angular-oauth2-oidc. When testing with POSTMAN and ThunderClient in VS Code, I managed to receive the correct response (the access_token). However, I am ...

Nested component in reactive forms not functioning as expected

I've been experimenting with creating nested reactive form components. Specifically, I'm working on a reusable input component for my app within a reactive form. How can I dynamically communicate with nested components in Reactive forms? Despite ...

Tips for effectively managing loading and partial states during the execution of a GraphQL query with ApolloClient

I am currently developing a backend application that collects data from GraphQL endpoints using ApolloClient: const client = new ApolloClient({ uri: uri, link: new HttpLink({ uri: uri, fetch }), cache: new InMemoryCache({ addTypename: f ...

Leveraging foreign key attributes within Angular templates

My technology stack includes Django for the backend with Django Rest Framework and Angular for the frontend. Within the backend, I have defined 2 models: class Post(models.Model): category = models.ForeignKey(Category, on_delete=models.SET_NULL, null= ...

Comparing the installation of TypeScript on Ubuntu utilizing npm versus native packages (via apt)

I'm looking to incorporate Typescript into my Ubuntu system and have come across two different methods to do so: Using sudo apt update && sudo apt install node-typescript -y Running sudo npm install -g typescript My main question revolves ar ...

The error message "unsupported_grant_type" was encountered while using the Django OAuth2 server

Having trouble getting django to accept my POST request for an access token. Despite having the correct parameters and authorization code, I keep receiving an error after sending the follow-up POST request. According to what I've read, the content-ty ...

Recursive types in TypeScript allow for the definition of types that

Is there a way to implement the function below without utilizing any? Playground type MyType = { name: string, age: number, score: { prime: number, }, prize: { first: { discount: number } } } export const trim = ( myObj: ...

Utilizing Express-WS app and TypeScript to manage sessions

I am currently working on setting up a node server using Typescript with the help of express and express-ws. My goal is to include Sessions in my application, so I have implemented express-session. Below you can find some pseudo code: import * as session ...

Bringing in a TypeScript module to an Angular component

Having trouble with including a specific library in my component Here is the code for my component which uses geolib as the library: import { Component, OnInit } from '@angular/core'; import { StationsService } from '../../../services/stati ...

Personalizing the predefined title bar outline of the input text field

The outline color of the title in the input textbox appears differently in Google Chrome, and the bottom border line looks different as well. <input type="text" title="Please fill out this field."> https://i.stack.imgur.com/iJwPp.png To address th ...

Typescript absolute imports are not being recognized by Visual Studio Code

Encountered a similar unresolved query in another question thread: Absolute module path resolution in TypeScript files in Visual Studio Code. Facing the same issue with "typescript": "^4.5.5". Here is the content of my tsconfig.json: { ...

Is it possible to integrate Angular8 components into AngularJS(1.x) by importing them as a node module?

Currently, I am in the process of developing an Angular 8 application. In this app, when a user clicks on a button, they should be redirected to a vendor portal that is hosted on a different web application with a different URL. When the user lands on the ...

Encountered an error while attempting to update an object: Unable to read property 'push' of undefined

Encountering an issue while attempting to update an object with additional information, receiving an error message stating 'property \'push\' of undefined'. /*Below is the object model in question:*/ export class Students { ...

Add a class to a button in an Angular btn-group if a specific string is found within an

I am currently working on a project where I have multiple buttons that need to toggle an active class when selected in order to change their color. Below is a snippet of what I have: In the array called 'selected', I have: this.selected = [&ap ...

Managing sessions in Typescript using express framework

Hey there, I'm just starting to learn about TypeScript and I have a question about how sessions are handled in Typescript. Could someone please explain the process of session initialization, storing user data in sessions, etc.? If you have any tutoria ...

I'm having an issue with my ng2-charts where data label values are not displaying in the graphs

I'm currently working on an Angular project that utilizes ng2-charts and chart.js. Interestingly, when I run the project locally, the datalabels are visible (check: project run locally). However, once I deploy the project onto a server, the datalabels ...

Working with multiple observables in an array of properties using RXJS

I'm relatively new to using rxjs in my angular projects and I'm facing a challenge with a simple scenario. When making an http call to retrieve a group, it returns data including a list of "buddy ids", "genre ids", and a "region id". In order t ...