Обмен данными через компоненты - PullRequest
2 голосов
/ 04 октября 2019

Я хочу передать данные в компонент navbar при входе в компонент входа, но содержимое моего navbar не обновляется.

Мой компонент navbar находится в модуле приложения, а компонент входа -в другом модуле.

Я пытался использовать службы для обмена данными.

Мой компонент входа в систему, этот компонент находится в другом модуле

export class LoginComponent {
  userCredentials;
  constructor(
    private readonly _authService: AuthService,
  ) {

  }

  login() {
    this._authService.auth(this.userCredentials)
      .subscribe(
        (response: any) => {

            const dataForm = {
              usuario: response.user,
              rol: this.response.role,
            };
            this._authService.setSession(response);
        },
        error => {
          console.log(error);
        }
      );
  }
}

Мой NavBarComponent, этот компонент находится в модуле приложения

export class NavbarComponent  {

  isLogged = false;
  susbscription: Subscription;
  constructor(
    private readonly _authService: AuthService,
  ) {
    this.suscripcion = this._authService
      .changeState$
      .subscribe(
        (isLogged) => {
          this.isLogged = isLogged;

        },
        error => console.log(error)
      );
  }
}

Мой NavBar Html

<mat-toolbar color="primary">
    <mat-toolbar-row>
      <span>SUPERMERCADO</span>
      <span class="spacer"></span>
      <div *ngIf="!isLogged">
        <button mat-button 
          Login
        </button>
      </div>
      <div *ngIf="isLogged">
        <p>Welcome</p>
      </div>
    </mat-toolbar-row>
  </mat-toolbar>

Мой сервис, этот сервис отсутствует в модуле приложения

  @Injectable()
export class AuthService {
  protected url = environment.url;
  protected model = '/user';

  isLogged = false;
  private changeState = new Subject<boolean>();
  changeState$ = this.changeState.asObservable();

  constructor(
    private readonly _router: Router,
    protected readonly httpclient: HttpClient,
  ) {
  }

  setSession(data: any) {
    this.isLogged = true;
    this.changeState.next(this.isLogged);
  }

  auth(dataForm: any): Observable<any> {
    const url = `${this.url}${this.model}/login`;
    return this.httpclient.post(url, dataForm);
  }

}

Я использую угловой 8.2.0

Ответы [ 4 ]

1 голос
/ 04 октября 2019

Может быть две причины, почему ваш код не работает должным образом.

  1. субъект changeState передает данные до , на который подписывается компонент navbar. Из того, что я могу понять, когда вы находитесь на странице входа, поэтому компонент navbar не должен быть загружен еще. Когда ты. В вашем LoginComponent вы сначала излучаете данные, затем, когда загружается NavbarComponent, вы подписываетесь на наблюдаемое, которое только что выпустило.
    Но, поскольку вы используете Subject , вы не получите значение последнего испущенного . Чтобы смягчить это, вы можете использовать BehaviorSubject , который будет сохранять последнее излученное значение для новых подписчиков .

Субъект против BehaviorSubject

const s = new Subject();

s.next('not seen...');
s.next('not seen...');
s.next('not seen...');

s.subscribe(d => console.log('SUBSCRIBER 1: ', d))

// You must first subscribe, as the `Subject` does not holds any values on itself

s.subscribe(d => console.log('SUBSCRIBER 2: ', d))

// `Subscriber 1` will also receive those
s.next('value1 !!');
s.next('value2 !!');

/* 
SUBSCRIBER 1: value1 !!
SUBSCRIBER 2: value1 !!
SUBSCRIBER 1: value2 !!
SUBSCRIBER 2: value2 !!
*/


const bs = new BehaviorSubject(null);

bs.next('not seen');

// It will retain only the last value for the new subscribers
bs.next('hmmm!!')

bs.subscribe(v => console.log('subscriber 1 of BS: ', v))

bs.next('value1!')
bs.subscribe(v => console.log('subscriber 2 of BS: ', v))

/* 
subscriber 1 of BS: hmmm!!
subscriber 1 of BS: value1!
subscriber 2 of BS: value1!
*/

Здесь - это демонстрация StackBlitz, если вы хотите исследовать.

Итак, если вы замените свой Subject с BehaviorSubject(null), оно должно работать.

Как вы упомянули, AuthService не является частью AppModule. Может быть шанс, что не получит синглтон .
Я думаю, вы можете исправить это, добавив декоратор Injectable({ providedIn: 'root' }) к своему классу AuthService (что также сделает дерево сервиса доступным для поиска).
1 голос
/ 04 октября 2019

Является ли компонент LoginComponent загруженным модулем с отложенной загрузкой?

Если это так, вам нужно добавить свойство autIn: 'root' в AuthService:

@Injectable({
  providedIn : 'root'
})

Убедитесь, что удалили егоиз свойств провайдера Модуля.

Если ваш LoginComponent загружен не с большой задержкой, убедитесь, что вы импортируете AuthService только один раз в AppModule. В противном случае вы можете получить несколько экземпляров AuthService.

Если вы хотите, чтобы AuthService был частью модуля, вы можете использовать шаблон forRoot, чтобы гарантировать, что службы импортируются только один раз:

@NgModule({
  // declarations, imports and exports only
})
export class SharedModule {

  static forRoot(): ModuleWithProviders {
  return { 
    ngModule: SharedModule,
    providers: [// your services]
  }
}

@NgModule({
  imports: [SharedModule.forRoot()]
})
export class AppModule {}

Если на Angular 8 вы также можете сделать:

@Injectable({
  providedIn: SharedModule
})
export class AuthService

Вы хотите, чтобы один и тот же экземпляр AuthService был доступен как для AppModule, так и для модуля, где находится ваш LoginComponent.

Наконец, если это не проблема, у вас может быть проблема, когда NavBarComponent подписывается на changeState $ observable после его выдачи. В этом случае вам нужно изменить changeState на BehaviorSubject, поэтому, когда NavBarComponent подписывается, он получает последнее переданное значение.

0 голосов
/ 04 октября 2019

Хранение данных в локальном хранилище и доступ к нему в любом месте компонентов, где вы хотите просто создать одну общую службу для извлечения информации и ее использования. По {{}} служебной части интерполяции строк

getUserInfo() {
   const savedCredentials = localStorage.getItem(credentialsKey);
    return JSON.parse(savedCredentials);
  }

Составная часть:

 this.currentUser = this.authService.getUserInfo();

и доступ к данным, подобным этому:

this.currentUser.BusinessDate
0 голосов
/ 04 октября 2019

Из компонента

    import { Component, OnInit, ViewChild} from '@angular/core';
    import { dataService } from "src/app/service/data.service";
    @Component( {
        selector: 'app-sideWidget',
        templateUrl: './sideWidget.html',
        styleUrls: ['./linked-widget.component.css']
    } )
    export class sideWidget{

    constructor( private LWTableColumnNames: dataService ) { 

    }

    ngOnInit() {
     this.LWTableColumnNames.refLWTableColumnNames =  "patient"; //this line of code will pass the value through data service

    }    
    }

Служба данных

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';

@Injectable()
export class dataService {
    refLWTableColumnNames: string;//creating an object for the data
}

В компонент

import { Component, OnInit } from '@angular/core';
import { dataService } from "src/app/service/data.service";

@Component( {
    selector: 'app-linked-widget',
    templateUrl: './linked-widget.component.html',
    styleUrls: ['./linked-widget.component.css']
} )
export class LinkedWidgetComponent implements OnInit {

    constructor(private LWTableColumnNames: dataService) { }

    ngOnInit() {
    console.log(this.LWTableColumnNames.refLWTableColumnNames); // out put will be string "patient"
    }

}

Демонстрация Stackbliz , таким образом, вы можете отправлять значения в разные дочерние компоненты (не только родительский дочерний компонент)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...