Angular2 - transferring data outside the router-exit to another component

I am new to Angular2, but I already made 30+ components and services and used Input, Output, ChangeDetectorRef, Pipes. So I almost know about Angular2. My app.component.ts is as follows

import { Component } from '@angular/core'; @Component({ selector: 'soc', template: ` <header-block></header-block> <router-outlet></router-outlet> `, }) export class AppComponent { } 

Since I need my header block on every page, so I added it outside the router block, so I don't need to add it everywhere. Now the problem I am facing is changing the value of the variable in the header block after completing the action inside the router.

For example, I have a menu that will be visible to the user only after logging in.

 {{ user_is_logged }} <ul class="nav navbar-nav navbar-right" *ngIf="user_is_logged == '1'"> <li><a href="#" (click)="logout($event)">Logout</a></li> </ul> 

user_is_logged is a variable whose value is received from localStorage in header.block.component.ts

 user_is_logged:string = localStorage.getItem("logged"); 

If the user is not registered, that is, user_is_logged has the value undefined for home.component.ts (where the login logic is written), I ask the user to log in and, after successful login, update the value of the user_is_logged variable, as well as updating the localStorage value of the variable, and then triggering change detection using ChangeDetectionRef (cdr) and then routing to the user profile

 this.user_is_logged = "1"; localStorage.setItem('logged', '1'); this.cdr.detectChanges(); this.router.navigate(['u/'+user_id']); //user_id is from login response from server 

The problem is that after successfully logging into the user profile, the value {{user_is_logged}} is never updated, even when I use this variable myself or using the value from localStorage or even causing a discovery.

Is it possible to do so, or do I need to add a title block to each page separately? Please ask for more information if I missed something.


EDIT =============>

So, going through the Subject, BehaviourSubject, AsyncSubject, ReplaySubject, Observables topic and that I just couldn't get it to work. This is the last code I wrote:

home.page.component.ts (where the login occurs and should issue an event)

 import { HomeService } from '../services/home.service'; // No observable or subject imported here. login() { // Sending status 1 to HomeService this.HomeService.changeStatus("1"); } 

home.service.ts (which is imported by both components)

 import { BehaviorSubject } from 'rxjs/BehaviorSubject'; // I imported Subject, BehaviourSubject, Observables but cant get it to work export class HomeService { // This looked more reliable than Subject so used this; init with value "0" public subjectStream = new BehaviorSubject<string>('0'); constructor( ){ this.subjectStream.subscribe(value => { // Successfully logs value "1" sent by changeStatus below console.log(value); }); } changeStatus(value: any){ // Gives value "1" when called by home.page.component.ts console.log(value); // Looks correct because it successfully sent value to construct this.subjectStream.next(value); } } 

header.block.component.ts

 import { HomeService } from '../services/home.service'; // No observable or subject imported here also. constructor( ){ this.HomeService.subjectStream.subscribe(value => { // Logs value "0" at beginning but never logs value "1" console.log(value); }); } 

My magazine

 // logged by constructor when imported by header.block.component home.service.ts:31 0 // logged by constructor of header.block.component itself header.block.component.ts:25 0 // logged by constructor when imported by home.page.component (I think) home.service.ts:31 0 // =================== // Login called here // =================== // logged by changeStatus after login after called by home.component home.service.ts:36 1 // logged by constructor after getting event from changeStatus home.service.ts:31 1 

What am I missing in header.block.component.ts? Since the value is successfully updated inside home.service.ts, but never goes into the header.

+5
source share
2 answers

If you provide HomeService on the home page and in the header, you get 2 instances of HomeService . If you want to share a service, specify it only once on the parent component. If you want to share one instance with your entire application, specify it only in @NgModule() AppModule

+1
source

It has been suggested posting this, this is an event / subject service for bare bones, so you get started. I use "notifier / notes / note", so the nomenclature is not confused with "events" and other framework-api mechanisms.

 // Constant of named "notes" analogous to named events. // I always found it easier to have one event type with a "name", // rather than creating a specific typed event for every action. const Notes = { HEADER_BUTTON_CLICKED : 'header_button_clicked' }; // Any component that wants to send data creates a new "Note" to send. // Just makes sure you know what all callbacks are getting. class Note { constructor ( name, data ) { this.name = name; // Should be from your Notes constant. this.data = data; // Can be anything at all. } } // You inject this service into any component that needs it. class NotifierService { constructor() { let Rx = require ( 'rx' ); // We'll use Subject here. this.subject = new Rx.Subject ( ); } // You only subscribe if you want to hear notes. subscribe ( callback ) { // Subscribing component feeds in a callback. // The return of this can be used to unsubscribe as well. return this.subject.subscribe ( b => callback ( b ) ); } // Any component with access to this service can just create a note // and send it to all subscribers to this service. sendNote ( note ) { // Component uses the service to emit a "note" with a // named event and a payload. All subscribers hear it in the // callbacks they subscribed with, and can filter on the name // in the "note" to make sure it the event they care about. // This is pretty naive but should give the idea. this.subject.onNext ( note ); } } export { NotifierService } // Service to inject export { Note } // A useful type to send out to subscribers export { Notes } // Constant of event/note names. 

Typical Usage:

 import { NotifierService, Notes, Note } from './notifier.service'; ... // inject in your constructor either TS or ES6 style... // I want to hear notes this.noteSvc.subscribe ( b => this.myCallback ( b ) ); // I want to send a note this.noteSvc.sendNote ( new Note ( Notes.HEADER_BUTTON_CLICKED, { btnName : 'Home' } ); // In the callback myCallback ( note ) { if ( note.name === Notes.HEADER_BUTTON_CLICKED ) { console.log ( note.data ); // whatever the payload is } } 
0
source

Source: https://habr.com/ru/post/1263504/


All Articles