Ibanez1408
Ibanez1408

Reputation: 5048

Change a property of a component from another component and render it in the html in angular 2

I have 3 components 'starter-left-side', 'starter-content', 'camera'. 1 service 'generalParameters'. In the generalParameters, I have 2 properties; 'contentHeader' & contentDescription which has default string values respectively.

Upon initialization of the starter-content, I get these values from the generalParameters and render it in starter-content.html. When I want to go to the camera.component, I just click on the link to the camera.component via the starter-left-side also, I have a method in the starter-left-side that sets the property value of the generalProperties as soon as the link is clicked so it can be used by the starter-content again.

I can successfully change the values in the generalProperties but the problem is, it is not rendered in the starter-component anymore. I do not know on which time of the life cycle hooks should I get the values from the generalProperties again so it can be rendered in the starter-content.html.

generaParameters.service.ts

contentHeader: string;
contentDescription: string;

constructor() {
  this.contentHeader = "Dashboard";
  this.contentDescription = "This is your dashboard";
}

starter-content.component.html

<h1>
  {{pageHeader}}
  <small>{{description}}</small>
</h1>

starter-content.component.ts

pageHeader: string;
description: string;

constructor(
  private gp: GeneralparametersService
) { }

ngOnInit() {
  this.pageHeader = this.gp.contentHeader;
  this.description = this.gp.contentDescription;
}

starter-left-side.component.ts

setContent(header, description) {
  this.gp.contentHeader = header;
  this.gp.contentDescription = description;
}

starter-left-side.component.html

<li class="active"><a href="avascript:void(0);" (click)="setContent('Camera', 'Using Camera')" [routerLink]="['camera']"><i class="fa fa-link"></i> <span>Camera</span></a></li>

Thank you very much for your help.

Upvotes: 1

Views: 56

Answers (2)

user6749601
user6749601

Reputation:

Use a Subject or BehaviorSubject in your Service. Thus, all components get updated when the value changes:

generaParameters.service.ts

import {BehaviorSubject, Observable} from 'rxjs';     

contentHeader: BehaviorSubject<string> = new BehaviorSubject('Dashboard');
contentDescription: BehaviorSubject<string> = new BehaviorSubject('This is your dashboard');

constructor() {}

public getContentHeader(): Observable<string> {
    return this.contentHeader.asObservable();
}

public setContentHeader(value: string): void {
    this.contentHeader.next(value);
}

public getContentDescription(): Observable<string> {
    return this.contentDescription.asObservable();
}

public setContentDescription(value: string): void {
    this.contentDescription.next(value);
}

starter-content.component.html

<h1>
  {{pageHeader}}
  <small>{{description}}</small>
</h1>

starter-content.component.ts

pageHeader: string;
description: string;

constructor(
  private gp: GeneralparametersService
) { }

ngOnInit() {
  this.gp.getContentHeader().subscribe(value => {
      this.pageHeader = value;
  });

  this.gp.getContentDescription().subscribe(value => {
      this.contentDescription = value;
  });
}

starter-left-side.component.ts

ngOnInit() {
   this.gp.getContentHeader().subscribe(value => {
      this.pageHeader = value;
   });

   this.gp.getContentDescription().subscribe(value => {
      this.contentDescription = value;
   });
}

setContent(header, description) {
  this.gp.setContentHeader(header);
  this.gp.setContentDescription(description);
}

starter-left-side.component.html

<li class="active"><a href="avascript:void(0);" (click)="setContent('Camera', 'Using Camera')" [routerLink]="['camera']"><i class="fa fa-link"></i> <span>Camera</span></a></li>

Upvotes: 1

Nico
Nico

Reputation: 2021

Since you are communicating using a service you can propagate your changes using an Subject

When you make changes to your subject via the gp.setContent since your other component is observing the changes they will be automatically updated.

I used pluck so that we can only take the properties we need and render them separately.

See my implementation. Hope it helps!!!

starter-left-side.component.html

<li class="active"><a href="javascript:void(0);" (click)="gp.setContent('Camera', 'Using Camera')" [routerLink]="['camera']"><i class="fa fa-link"></i> <span>Camera</span></a></li>

generaParameters.service.ts

import { Subject } from 'rxjs';

  private mycontent$ = new Subject();

  public content$ = this.mycontent$.asObservable();

  setContent(header, description) {
    this.content$.next({header, description});
  }

starter-content.component.ts

import { pluck } from 'rxjs/operators';
  ngOnInit(): void {
    this.pageHeader$ = this.gp.content$.pipe(pluck('header'));
    this.pageDescription$ = this.gp.content$.pipe(pluck('description'));
  }

starter-content.component.html

<h1>
  {{pageHeader$ | async }}
  <small>{{pageDescription$ | async}}</small>
</h1>

Upvotes: 2

Related Questions