2

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?

2

3 Answers 3

3

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

Sign up to request clarification or add additional context in comments.

3 Comments

Thankyou so much. It is working. Checked it in demo. Let me check this solution with actual code and scenario, I will accept the answer.
Will try the second alternative but seems somewhat similar to What siddhart has answered. And that solution did not work once I update the value of variable which reference static property the actual property changed. But ur solution has used method instead of property so may be it work differently. Thanks for solving my problem.
@Simer it's not a method, it's a getter. Even if you do Constants.DEFAULT_FILTERS.page = 3 it won't change the value, you can check it on the snippet. Cheers :{D
1

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;
  }
}

3 Comments

So I will be able to change this.params['filters']['page'] value in component class i.e the variable which is using that static readonly property of constant class?
Of course. Try logging this.params to the console. I could see the value getting updated.
@Siddarth Applied your solution but it changes value of DEFAULT_FILTERS when console.log in component class.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.