1

I would like to change the value of the variable named bdg_m_1 from an another component. I am able to change the value of bdg_m_1 from the same typescript file.. Here is my code..

Filename : nav.ts

var bdg_m_1:string = "10" ; // HOW TO CHANGE THIS VALUE FROM ANOTHER COMPONENT

export const navItems: INavData[] = [
  {
    name: "Menu 1",
    url: "/menu_1",
    icon: "icon-speedometer",
     badge: {
       variant: 'info',
       text: bdg_m_1, 
     }
  }, 
];
user3661448
  • 45
  • 1
  • 9

6 Answers6

2

You could type the following code in nav.ts

let config = {
    bdg_m_1 : "10",
    navItems: [{
        ...
    }]
}
module.exports = config;

And when you want to include config object,

var Config = require('nav.ts');
console.log(Config.bdg_m_1);
Metalgear
  • 3,391
  • 1
  • 7
  • 16
1

You just need to export it, then import it in the component that you want to change it.

Declaration:

export let bdg_m_1:string = "10" ;

Other component:

import bdg_m_1 from 'nav.ts';

bdg_m_1 = '11';

EDIT: The above "solution" is actually wrong. However I am leaving it in place because it is instructive about something that is counter-intuitive on how Typescript import/export works.

See this explanation for a good explanation of what is going on.

The upshot is that in the importing module, the big_m_1 actually is a binding, not a variable. So in effect it is read-only.

What you apparently can do is this:

import thing = require('./nav.ts');
thing.bdg_m_1 = '11';

Good luck.

AlanObject
  • 9,613
  • 19
  • 86
  • 142
  • AlanObject, Thanks for your help... I am getting the below error in myComponent, I have also declared export let bdg_m_1:string = "10" ; in nav.ts ...import bdg_m_1 'bdg_m_1' is declared but its value is never read.ts(6133) Module '"d:/angular/_nav"' has no default export. Did you mean to use 'import { bdg_m_1 } from "d:/angular/_nav"' instead?ts(2613) Property 'bdg_m_1' does not exist on type 'myComponent'. – user3661448 May 29 '20 at 06:15
  • AlanObject, I am not able set the value, but i am able to get the value after changing the code like this... import * as a from '../../_nav'; a.bdg_m_1... – user3661448 May 29 '20 at 06:37
0

You could send it through an eventEmitter if they are parent-child related. Here is an example on stackblitz, and the code in case it does not works :

child-component.ts:

import { Component, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent {
  nameToSend = '';
  @Output() newNameEmitter = new EventEmitter<string>();

  emitNewName () {
    this.newNameEmitter.emit(this.nameToSend);
  }
}

chil-component.html:

<input type="text" [(ngModel)]="nameToSend"/>
<button (click)="emitNewName()">Send new name</button> 

app.ts:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';

  changeName(newName: string){
    this.name = newName;
  }
}

app.html:

<app-child (newNameEmitter)="changeName($event)"></app-child>
<br>
name = {{name}}

The principle is to emit a value whenever you want. you catch it in the parent with (newNameEmitter)="changeName($event)" (app.html)

Quentin Grisel
  • 4,794
  • 1
  • 10
  • 15
0

What you actually want to do, is to manage your application's (global) state.

Option 1: Using nested components

In case you have a parent- and a child-component, just use EventEmitters. Could look like:

nav.ts

export enum MenuName = {
  Menu1 = 'Menu 1',
  Menu2 = 'Menu 2'
}

export const navItems: INavData[] = [
  {
    name: MenuItem.Menu1,
    ...
  }, 
];

child.component.ts

@Output() badgeChange = new EventEmitter<{menuName: MenuName, value: string}>();

private updateBadge(menuName: MenuName, value: string) {
  this.badgeChange.next({menuName, value});
}

and listen to the change in your parents HTML: <app-child (badeChange)="onBadgeChanged($event)"></app-child> and in TS:

onBadgeChanged(change: {menuName: MenuName, value: string}): void {
  // find menu item by `change.menuName`
  // update it's badge value
}

Option 2: Use a service for global state

If your global state is simple, you can also use a service for your state:

nav-service.ts

export class NavService {
  navData$ = new BehaviourSubject<INavData[]>([
    {
      name: "Menu 1",
      ...
    }, 
  ]);

  updateBadge(menuItemName: string, value: string): void {
    // find menu item by `menuItemName` in `this.navData$.value`
    const menuItem = ...;
    if (menuItem) {
      menuItem.badge.text = value;
      this.navData$.next([...this.navData$.value]); // emit new nav data
    }
  }
}

In this case, your menu-component would listen to changes of this.navService.navData$ and the component or service which updates the data, uses this.navService.updateBadge(...) to tell everyone that the value has changed.

Option 3: Use a state management library

If your state is more complex than just a menu, I would suggest to use a state library such as NgRx, NgXs or Akita. Follow the links to learn more about them, I use NgRx for my projects. The idea is similar to using an own service for state, except the entire state is kept in one state-object and more sophisticated concepts are introduces by these libraries.

sschmid
  • 1,341
  • 1
  • 16
  • 22
0

You can not change the value of the variable from any other component as this variable is not accessible from that component.

You dont have to do anything big. You just have to export this variable and import this variable in the other component.

Export bdg_m_1:string = '10'

And import the variable using.

import bdg_m_1 from nav.ts

And change the value from the other component using.

bdg_m_1 = 'abc'

You can also change the name while importing the variable by using:

import bdg_m_1 as myConst from nav.ts
myConst = 'abc'
Minal Shah
  • 1,402
  • 1
  • 5
  • 13
  • Dear Minal Shah, Thanks for your reply... I tried your code...I am able to read the value from nav.ts to another component, but i am not able to set (change) the value..It is showing me this error in other component : Cannot assign to 'bdg_m_1 ' because it is a read-only property.ts(2540). Can you please help... – user3661448 May 29 '20 at 07:37
  • I have one more solution to this. Please try that solution. – Minal Shah May 29 '20 at 07:59
0

I have another suggestion for this, you make your ts file injectable and create method to update the value of your variable and use that method in your another component to update the value. your service would look something like this.

@Injectable()
export class MyService {

 bdg_m_1 : string = '10';
 navItems: INavData[] = [
     {
        name: "Menu 1",
        url: "/menu_1",
        icon: "icon-speedometer",
        badge: {
          variant: 'info',
          text: bdg_m_1, 
      }
   }, 
   ];
  constructor(){}
  setValue(value: string){
           this.bdg_m_1 = value;
     }
  getNavItems(){
  return this.navItems;
    }
   }

And get instance of this service in your another component and call the method setValue to change the value of bdg_m_1.

So add following code in your component:

constructor(private myService: MyService){
   this.myService.setValue('abc');
  }
Minal Shah
  • 1,402
  • 1
  • 5
  • 13
  • Dear Shah, Thank you once again..The export const navItems is a pre defined one in coreUI Template and we can't modify this...As per your code, I am able to export a value from a myComponent to nav.ts successfully. The export statement outside the export class is working fine. I want to pass the value from ngOnInit of myComponent. Can you please give me a solution. Thanks a lot for your help... – user3661448 May 29 '20 at 08:29
  • export const bdg_m_1 : string = '10'; // This value is sent successfully @Component({ templateUrl: "myComponent.component.html", }) export class MyComponentComponent implements OnInit { ngOnInit(): void { bdg_m_1 = 11; // <<<< I want this value to be sent ... } ... } – user3661448 May 29 '20 at 08:30