What is the best way to ensure that my variable updates whenever its reference changes?

Having trouble updating an Angular2 component's variable that is tied to a variable in another service? You're not alone. I've been struggling to get it to update without constantly resetting the variable.

In my component, I have the following code inside ngOnInit:

ngOnInit(){
   this.rooms = this.globals.filteredRooms;
}

Meanwhile, in my @injectable called AppGlobals, I find myself frequently writing code like this:

applyFilters() {
    this.filteredRooms = this.rooms.filter(r => this.campFilters.includes(r.camp));
}

The issue arises when I want the rooms variable in my component to automatically change whenever the filteredRooms variable in appGlobals changes. Instead of this automatic update, I keep having to manually set this.rooms = this.globals.filteredRooms over and over again.

I've attempted various solutions such as trying (and failing) to create an Observable and subscribe to it, importing my component into appGlobals to trigger updates (resulting in mysterious errors), and exploring the idea of using byRef specification to establish a reference rather than making copies.

If changing to a reference is indeed necessary, how can that be achieved? How do I go about creating an Observable and subscribing to it if that's the solution? Or perhaps there's a different approach altogether that I'm missing?

Answer №1

There is a limitation to what you are trying to achieve, and here's the explanation:

let x = [1, 2];
console.log(x); // [1, 2]

let y = x;
console.log(y); // [1, 2]

x = [1, 2, 3];

console.log(x); // [1, 2, 3]
console.log(y); // [1, 2]

By assigning x = y, both variables point to the same memory location (in this case, [1, 2]).
When you modify y, it only changes what y points to, while x still points to the original value.

To avoid this issue, you can use a container for the value, such as:

interface Ref {
    val: number[];
}

let x = { val: [1, 2] };
console.log(x.val); // [1, 2]

let y = x;
console.log(y.val); // [1, 2]

x.val = [1, 2, 3];

console.log(x.val); // [1, 2, 3]
console.log(y.val); // [1, 2, 3]

Since you haven't provided the part of your code where filteredRooms is declared, I cannot give you an exact solution, but you can infer from my example.

If you need to perform similar tasks multiple times, consider using a helper class like this:

class Ref<T> {
    private val: T;

    public set(value: T): void {
        this.val = value;
    }

    public get(): T {
        return this.val;
    }
}

Answer №2

After struggling for days with no progress on this issue, I finally managed to create the Observable right after posting this question. It's quite ironic how things work out sometimes. Here is the solution in case it can help someone else:

In my AppGlobals class:

@Injectable()
export class AppGlobals {

    private _filteredRooms = new BehaviorSubject(this.rooms);

    public filteredRooms = this._filteredRooms.asObservable();

    public rooms = [];


    constructor(private roomSvc: RoomSvc) {
        this.getRooms();
    }

    applyFilters() {
        this._filteredRooms.next(this.rooms.filter(r => this.campFilters.includes(r.camp)));
    }

    getRooms() {
        this.roomSvc.getRooms()
            .subscribe(r => {
                    this.rooms = r;
                    this._filteredRooms.next(this.rooms);
                }
            );
    }
}

Also, remember to import BehaviorSubject from 'rxjs/BehaviorSubject'

Inside my component:

export class TableComp {
   roomSubs: Subscription;
   rooms: Array<any>;
constructor(private globals: AppGlobals) { }

    ngOnInit() {

        this.roomSubs = this.globals.filteredRooms
            .subscribe(r =>
                this.rooms = r
            );
    }
}

Note that you need to import Subscription from 'rxjs/Subscription'

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

Tips for efficiently utilizing Hooks with React Context:

I am currently working on my application and utilizing React Context with the setState function. const userContext = React.createContext([{ user: {} }, () => {}]); const userHook = useState({ user: {} }); <userContext.Provider value={userHook}> / ...

When a model is changed from within a jQuery event, Angular 2 fails to update the view

During the development process, I encountered an issue while creating a custom search panel that displayed search results in a dropdown container. In my controller, I defined the following: export class ProductSearchComponent implements OnInit { publ ...

Efficiently utilizing ngrx by orchestrating various services and actions to achieve accurate mapping

Combining multiple effects into one is my current goal due to an issue with dispatching actions separately. The aim is to execute sequentially after verifying the value returned from the first service call. Here are the three separate effects I have: @Eff ...

Split panel vertically with a draggable divider allowing you to customize the height of each section

Recently diving into Angular, I'm working on a vertically split panel with a "drag handle" that allows users to adjust the height of the top and bottom tree panels. While I've managed to implement a three-stage toggle, I'm struggling to get ...

Embark on a journey through a preorder traversal of a Binary Tree using TypeScript

Hello! I've been tasked with creating a function that iterates over a binary tree and returns all its values in pre-order. Here is the code snippet: interface BinTree { root: number; left?: BinTree; right?: BinTree; }; const TreePreArray ...

"Having trouble subscribing? The first attempt doesn't seem to be working

I'm currently working on some TypeScript code that searches for the nearest point around a user in need of car assistance by checking a database. Once the nearest point is identified, the code retrieves the phone number associated with it and initiate ...

What is your approach to organizing the HTTP requests in your Angular 2+ application?

I'm looking for suggestions on how to better organize my API calls within my services. How have you structured your API calls? Do you centralize all API calls for the entire application in one dedicated service? Do you create an HTTP folder and sepa ...

What kind of Input field is being provided as an argument to a TypeScript function?

Currently, I am working through an Angular 2 tutorial where an input element is being passed to a function through a click event. The tutorial includes an addTodo function with the following signature: addTodo(event, todoText){ }. However, there is a warn ...

Encountering a schematic flow error while utilizing the angular cli for project creation

Currently, I am in the process of learning Angular. I have successfully installed Node.js version 14 and AngularCLI, but when I attempt to create a new project using the command 'ng new proj', an error is encountered. During the package install ...

Combining Arrays Together in TypeScript

I am in need of a solution to merge two arrays into one using TypeScript. First Array Object: export interface Item{ Label : string, Code : string, Price : number, } Second Array Object: export interface Amou ...

How can the center element be aligned without recursively centering all children?

How can I center all children within a particular element without affecting their children? <Col style={{ textAlign: "center" }}> <Space>...</Space> <div>...</div> </Col> In this scenario, I am utilizing t ...

What is the process for activating shift key - multi-selection in the PrimeNG pick list?

I'm currently utilizing the prime ng pick list from the PrimeNG API located at: https://www.primefaces.org/primeng/#/picklist An issue I've encountered is that the picklist doesn't support multiple selections. For instance, in this example ...

The default value in an Ionic select dropdown remains hidden until it is clicked for the first time

Having an issue with my ion-select in Ionic version 6. I have successfully pre-selected a value when the page loads, but it doesn't show up in the UI until after clicking the select (as shown in pic 2). I'm loading the data in the ionViewWillEnt ...

Creating a Component with a flexible template: (Using transclusion and an inline template)

Trying to come up with a solution for creating a component that can work with dynamic template strings and access local variables within the template has proven to be quite challenging. No matter what approach I take, I always seem to struggle with getting ...

Dynamic parameterization of Angular form controls

I'm facing an issue with adding validators to a form where some controls are required only if a specific condition is met by another control. I initially created a custom validator function that takes a parameter to determine the requirement, but the ...

Guide on creating a Typescript function with a strongly typed argument

I am looking to develop a function that accepts a type created using export class and imported in the traditional manner as an extension of a particular type. With a base Page class and various derived classes, I aim to have this function capable of receiv ...

Investigating sibling HTML elements using an Angular directive

When working with Angular 10, my goal is to access a sibling element within my directive. This is illustrated by the following code snippet: <label myDirective for="foo" ... <input id="foo" formControlName="xyz" ... Wit ...

Closing a modal using the Enter key in Angular 6

I was able to replicate the issue on StackBlitz using minimal code. To reproduce: Step 1: Input a word in the text field and press Enter on the keyboard. Step 2: A modal will pop up. Step 3: Hit Enter again on the keyboard. During Step 2, I encou ...

The PhpStorm code completion feature is not functioning properly when working with TypeScript code that is distributed through NPM

I am facing an issue with two NPM modules, which we will refer to as A and B. Both modules are written in TypeScript and compile into CommonJS Node-like modules. Module B has a dependency on module A, so I have installed it using the command npm install ...

The promise callback in Angular2 is unable to access this

This snippet of code is quite odd, but it resides within a service context: constructor() { gapi.load('client:auth2', this.loadGoogleApi); } private loadGoogleApi() { // Array of API discovery doc URLs for APIs used by the quickstart ...