Переменная не обновляется в NgOnInit - PullRequest
0 голосов
/ 02 марта 2020

Я создаю приложение, которое использует два компонента:

  1. nav
  2. content

, оно также использует общую службу, которая выполняет вызовы API и хранит общие функции:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class ApiService {
    url = 'api address';
    element_id;
  constructor(private http: HttpClient) { }
  public getMenus(){
    return this.http.get(this.url);
  }
  public getData(element_id){
    console.log('This ' + element_id + ' comes from api.getData')
    return this.http.get(this.url);
  }
  public change_val(element_id){
    console.log('This ' + element_id + " comes from api.change_val");
    this.element_id = element_id;
  }
}  

компонент навигации

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { ApiService } from '../api.service';

@Component({
  selector: 'app-nav',
  templateUrl: './nav.component.html',
  styleUrls: ['./nav.component.css']
})
export class NavComponent implements OnInit {
  menus;
  constructor(private api: ApiService,){}
  ngOnInit(){
    this.api.getMenus().subscribe((data: any[]) => {
      //console.log(data);
      this.menus = data;
  });
  }
 public change_val(element_id){
    console.log("This " + element_id + " comes from nav.component")

    this.api.change_val(element_id)
    this.api.getData(element_id)
 }
}

компонент содержимого

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { ApiService } from '../api.service';

@Component({
  selector: 'app-content',
  templateUrl: './content.component.html',
  styleUrls: ['./content.component.css']
})
export class ContentComponent implements OnInit {
  content;
  constructor(private api: ApiService) { }

  ngOnInit(){
   this.api.getData(this.api.element_id).subscribe(res => {
   this.content = res[this.api.element_id];
   console.log("This " + this.api.element_id + " is coming from content getData")
  });
 }
}

В приведенном выше content.component.ts, строка в console.log не определена при первом запуске приложения.

Используя следующий интерфейс от nav.component. html, я могу передать одно и то же значение идентификатора всем функциям следующим образом:

<div *ngFor="let menu of menus; index as id">
    <ul>
        <li><button (click)="change_val(id)">{{menu['course-lesson-name']}}</button></li>
    </ul>
</div>

После проверки можно увидеть общую переменную element_id устанавливается без значения в сервисе и должен обновляться, когда пользователь нажимает на каждую кнопку в представлении. Когда приложение впервые открывается или обновляется, element_id не определен (не уверен, как это исправить), но как только я нажимаю любую кнопку, element_id в компоненте nav и службе обновляется, но не в компоненте содержимого.

Запускается ли ngOnInit один раз, а затем снова, пока приложение не обновится? Мне нужно следующее для обновления каждый раз, когда изменяется element_id.

   this.api.getData(this.api.element_id).subscribe(res => {
   this.content = res[this.api.element_id];
   console.log("This " + this.api.element_id + " is coming from content getData")

1 Ответ

0 голосов
/ 02 марта 2020

ngOnInit запускается только один раз, после создания экземпляра компонента, который вы хотите использовать здесь, необходимо уведомить заинтересованные компоненты об изменениях, настройте свой сервис следующим образом:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
// replay subjects cache values and replay them to new subscribers, good for timing problems
import { ReplaySubject } from 'rxjs'

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  url = 'api address';

  private elementIdSource = new ReplaySubject(1); // private subject
  elementId$ = this.elementIdSource.asObservable(); // public observable

  constructor(private http: HttpClient) { }
  public getMenus(){
    return this.http.get(this.url);
  }
  public getData(element_id){
    console.log('This ' + element_id + ' comes from api.getData')
    return this.http.get(this.url);
  }
  public change_val(element_id){
    console.log('This ' + element_id + " comes from api.change_val");
    // next on source to notify consumers
    this.elementIdSource.next(element_id)
  }
}  

затем в своем компоненте вы подпишитесь, чтобы получать изменения:

 // operators need to be imported
 // switchMap takes an observable value and switches into a new observable based on it
 // map takes an observable value and transforms it
 import {switchMap, map} from 'rxjs/operators'

 ngOnInit(){
   // subscribe to elementId$ changes (save your subscription!)
   this.idSub = this.api.elementId$.pipe(
     //switch into data fetch and map into the proper key
     switchMap(elementId => this.api.getData(elementId).pipe(map(res => res[elementId])))
   ).subscribe(data => {
     this.content = data;
     console.log(data, " is coming from content getData")
   });
 }

ngOnDestroy() {
  this.idSub.unsubscribe(); // clean up subscription to avoid memory leak!
}

теперь ваш компонент всегда будет знать, когда что-то изменится. Модель общего сервиса в основном всегда использует такую ​​модель.

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