Always_a_learner
Always_a_learner

Reputation: 5055

const value changing when variable accessing that const is updated in angular/typescript

This is stackblitz demo (not exact but somewhat idea of what problem I am trying to tell)

I have defined a const in src/app/constants/app.ts

export const DEFAULT_FILTERS = {
    "page":1,
    "perPage":10,
    "sortOrder": "asc",
    "tag":"all",
    "sortBy":"firstname"
}

I have done this to remove clutter from different interconnected components where I need to define filters as a variable and then using it.

listing.component.ts

import { DEFAULT_FILTERS} from '@app/constants/app';

export class listingComponent implements OnInit, OnDestroy {

    private for = someOtherconstant; // some other const used here.

    private params = {
        "filters": DEFAULT_FILTERS,
        "for": this.for
    }

    getNewRecords(pageNum) {
        console.log('default filters', DEFAULT_FILTERS)
        this.currentPageNum = pageNum;
        this.params['filters']['page'] = this.currentPageNum; 
        this._service.triggerCallForUsersObservable(this.careGroupParams)
    }
}

The console.log inside getNewRecords prints DEFAULT_FILTERS which I have changed no where still the page index inside DEFAULT_FILTERS because I am changing this.params['filters']['page'] = this.currentPageNum. Why?

I need a global const which I want to keep const for diff components so that I can reset the filters value whenever required.

EDIT:

If I use object.freeze then I am not able to change the property this.params like:

this.params['filters']['name'] = 'xyz'

So what could be the other way to keep DEFAULT_FILTER as global variable/const and then I can access it or change it and change the new variable which is accessing it but not the global val?

Upvotes: 2

Views: 6985

Answers (3)

user11287096
user11287096

Reputation: 11

You can use deep copy, as it allocates separate memory location for the new object, so changing "this.params" values in your case will not change the value of page index inside "DEFAULT_FILTERS".

Ex. var employee = { eid: "E102", ename: "Jack", eaddress: "New York", salary: 50000 } var newEmployee = JSON.parse(JSON.stringify(employee)); // DEEP COPY

Now if we make any change in "newEmployee" it will not make any change in "employee" as we are doing deep copy.

But if we simply do,

var newEmployee = employee; // SHALLOW COPY

and now we make any change in "newEmployee" it will reflect in "employee" as well, as we are doing shallow copy.

Upvotes: 0

SiddAjmera
SiddAjmera

Reputation: 39432

Here's what you can do to fix this. Create a class for Constants instead of a const. Declare a static getter variable inside it. static so that you don't have to create an instance of this class to use the constant. And then use it in your Component class. Something along the lines of this:

Constants Class

export class Constants {
  static get DEFAULT_FILTERS() {
    "page": 1,
    "perPage": 10,
    "sortOrder": "asc",
    "tag": "all",
    "sortBy": "firstname"
  }
}

Component Class

import {
  Component,
  Input
} from '@angular/core';
import {
  Constants
} from '../app/constants/app'
@Component({
  selector: 'hello',
  template: `<h1> {{name}}!</h1>
  <button (click)='getUsers()'>click me to see change in default filters const</button>`,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent {
  @Input() name: string;
  params = {
    "filters": Constants.DEFAULT_FILTERS
  }

  getUsers() {
    console.log('default filters', Constants.DEFAULT_FILTERS)
    this.params['filters']['page'] = 2;
  }
}

Upvotes: 1

lenilsondc
lenilsondc

Reputation: 9800

You can copy the const value instead of referencing it. However, as soon as you copy, it loses the connection with the original value; nonetheless, as it is a const value, it is not supposed to be changed, so it wouldn't be a problem.

You can copy the object by using the ... (spread) operator like the code bellow:

private params = {
    "filters": { ...DEFAULT_FILTERS },
    "for": this.for
}

Alternatively, you can create a class with a static property getter that always return a fresh object so there is no risk of losing the original value.

class Constants {
  static get DEFAULT_FILTERS() {
    return {
      "page": 1,
      "perPage": 10,
      "sortOrder": "asc",
      "tag": "all",
      "sortBy": "firstname"
    }
  }
}

let myDefaultFilter = Constants.DEFAULT_FILTERS;
myDefaultFilter.page = 2;
Constants.DEFAULT_FILTERS.page = 3; // forcing changes

console.log(myDefaultFilter.page) // changes
console.log(Constants.DEFAULT_FILTERS.page) // stays the same

Upvotes: 3

Related Questions