如何在每个选定选项更改时在组件之间共享数据?

时间:2019-07-15 21:52:45

标签: angular typescript components

我有两个组件,app.component和encours.component,我的app.component的导航栏中有一个选择,需要在每次更改时向encours.component发送值。第一次我可以得到价值,但是之后我什么也得不到。我有一个名为dataService的通信服务,并且我使用路由器出口进行路由,因此无法传递来自router-outlet标签的数据 我试图在encours.component中实现ngOnChange方法,但是它不起作用。

这是我的服务代码:

@Injectable()
export class DataService{

  private serviceSource = new BehaviorSubject(3);
  currentService = this.serviceSource.asObservable();

  constructor(){}

  changeService(service: number){
    this.serviceSource.next(service);
  }

}

这是我的app.component.html代码:

<nav class="navbar navbar-expand-lg navbar-light bg-light">

  <a class="navbar-brand" href="#">SAFRAN</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
    <form class="form-inline my-2 my-lg-0" *ngIf="showSelect">
      <select class="custom-select" id="service" #serviceSelect [(ngModel)]="service" name="service" (change)="setSelection(serviceSelect.value)">
        <option *ngFor = "let service of listeServices" value="{{service.id}}">{{service.nom}}</option>
      </select>
    </form>
</nav>

<router-outlet>
</router-outlet>

这是我的app.component.ts代码:

export class AppComponent implements OnInit{

  public listeServices: any;
  service: number;

  constructor(private router:Router, private serviceServ : ServiceService, private data : DataService) {
    router.events.forEach((event) => {
      if(event instanceof NavigationStart) {
        //I get some data from an API
        this.getServices();
        //I show the select only if the route is encours
        this.showSelect = event.url === "/encours";
      }
    });
  }

  ngOnInit(): void {
    this.data.currentService.subscribe(service => this.service = service)
  }

  public setSelection(selectedValue: any): void {
    this.service = selectedValue;
    this.data.changeService(selectedValue);
  }

这是encours.component.html文件:

<table *ngIf="listeFamilles">
  <tbody>
    <tr *ngFor="let f of listeFamilles">
      <th style="vertical-align: middle; padding-left: 10px;">{{ f.nom }}</th>
      <td  id="{{f.nom}}"  style="vertical-align: top;"></td>
    </tr>
  </tbody>
</table>

最后,我的encours.component.ts:

export class EncoursComponent implements OnInit, OnChanges{

  service : number;

  constructor(private serviceFam: FamillesService, private serviceOpe: OperationsService, private serviceVar: VarianteService, private serviceAff: AffaireService, private serviceAffecter: AffecterService, private data : DataService) {
    this.data.currentService.subscribe(service => this.service = service);
  }

  //This function is never called
  ngOnChanges(changes: SimpleChanges): void {
    console.log(changes);
  }

2 个答案:

答案 0 :(得分:2)

只要该值发生更改,就会调用您在 encours.component.ts 中对 DataService data字段的订阅,因此该组件实际上是已经收到此数据。对于这样的用例,实现接口ngOnChanges会很麻烦,因为该组件已经在构造函数中的订阅中接收到更新的值。

在构造函数中更改订阅行以控制台记录此更新:

this.data.currentService.subscribe(service => {
    console.log(service);
    this.service = service;
}); 

现在可以看到实际上已经是这种情况了。

如果您想(我认为是冗长的话)解雇onChanges()并在那里处理更新,则需要进行额外的工作。仅当具有onChanges()属性的属性发生更改时,@Input才会触发。这将要求您通过模板通过异步管道实现 DataService currentService的值作为@Input的模板。

可在以下位置找到实现此目标的示例:https://www.concretepage.com/angular-2/angular-2-4-onchanges-simplechanges-example。这里的官方文档:https://angular.io/api/core/OnChanges

答案 1 :(得分:0)

// This function is never called
  ngOnChanges(changes: SimpleChanges): void {
    console.log(changes);
  }

当然,当任何数据绑定属性发生更改时,就会调用ngOnChanges挂钩, 因此,如果它仅在组件 EncoursComponent 具有 @Input 属性的情况下起作用。