【问题标题】:On click event, change input field in a sibling component在单击事件时,更改同级组件中的输入字段
【发布时间】:2016-03-05 02:12:25
【问题描述】:

我正在尝试检测子组件中的点击。在其兄弟组件中,我想清空其中的输入字段。让我用一个简短的例子来说明我的意思:

// Parent component template:
<div>
  <child1-comp></child1-comp>
  <child2-comp></child2-comp>
</div>

.

// child1-comp template:
<input type="text" #inputText (keyup)="0">

.

// child2-comp template:
<ul>
  <li (click)="onClick(text1.value)" #text1>Test</li>
  <li (click)="onClick(text2.value)" #text2>Test2</li>
</ul>

child2-comp 中的一个点击事件之后,我想清空child1-comp 中输入字段中的值。

在 Angular 2 中可以做到这一点吗?

【问题讨论】:

  • 有几个选项,查看官方食谱,章节Component Interaction 示例。
  • @Sasxa 我尝试使用来自child2 的事件发射器,它只会发出一个布尔值。在父级中,我抓取了$event 并将其存储在一个变量中。然后将此变量传递给child1。我尝试使用*ngIf,但遇到了模板问题。我在正确的轨道上吗?还是我应该寻找其他方法?
  • 你能用你的设置创建一个plunker吗?

标签: angular


【解决方案1】:

通过服务进行组件间通信

当组件不处于父子关系时,只需创建和服务使它们相互通信,一旦创建服务,您就可以调用或使用订阅者重新路由调用。

import { Injectable } from '@angular/core';
import { Subject }    from 'rxjs/Subject';
@Injectable()
export class MissionService {
  // Observable string sources
  private missionAnnouncedSource = new Subject<string>();
  private missionConfirmedSource = new Subject<string>();
  // Observable string streams
  missionAnnounced$ = this.missionAnnouncedSource.asObservable();
  missionConfirmed$ = this.missionConfirmedSource.asObservable();
  // Service message commands
  announceMission(mission: string) {
    this.missionAnnouncedSource.next(mission);
  }
  confirmMission(astronaut: string) {
    this.missionConfirmedSource.next(astronaut);
  }
}


import { Component }          from '@angular/core';
import { MissionService }     from './mission.service';
@Component({
  selector: 'mission-control',
  template: `
    <h2>Mission Control</h2>
    <button (click)="announce()">Announce mission</button>
    <my-astronaut *ngFor="let astronaut of astronauts"
      [astronaut]="astronaut">
    </my-astronaut>
    <h3>History</h3>
    <ul>
      <li *ngFor="let event of history">{{event}}</li>
    </ul>
  `,
  providers: [MissionService]
})
export class MissionControlComponent {
  astronauts = ['Lovell', 'Swigert', 'Haise'];
  history: string[] = [];
  missions = ['Fly to the moon!',
              'Fly to mars!',
              'Fly to Vegas!'];
  nextMission = 0;
  constructor(private missionService: MissionService) {
    missionService.missionConfirmed$.subscribe(
      astronaut => {
        this.history.push(`${astronaut} confirmed the mission`);
      });
  }
  announce() {
    let mission = this.missions[this.nextMission++];
    this.missionService.announceMission(mission);
    this.history.push(`Mission "${mission}" announced`);
    if (this.nextMission >= this.missions.length) { this.nextMission = 0; }
  }
}



import { Component, Input, OnDestroy } from '@angular/core';
import { MissionService } from './mission.service';
import { Subscription }   from 'rxjs/Subscription';
@Component({
  selector: 'my-astronaut',
  template: `
    <p>
      {{astronaut}}: <strong>{{mission}}</strong>
      <button
        (click)="confirm()"
        [disabled]="!announced || confirmed">
        Confirm
      </button>
    </p>
  `
})
export class AstronautComponent implements OnDestroy {
  @Input() astronaut: string;
  mission = '<no mission announced>';
  confirmed = false;
  announced = false;
  subscription: Subscription;
  constructor(private missionService: MissionService) {
    this.subscription = missionService.missionAnnounced$.subscribe(
      mission => {
        this.mission = mission;
        this.announced = true;
        this.confirmed = false;
    });
  }
  confirm() {
    this.confirmed = true;
    this.missionService.confirmMission(this.astronaut);
  }
  ngOnDestroy() {
    // prevent memory leak when component destroyed
    this.subscription.unsubscribe();
  }
}

https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

【讨论】:

  • 这仍然是可接受的技术吗?即使是 Angular 6?
【解决方案2】:

我建议如下:

// Parent component template:
<div>
  <child1-comp [(value)]="value"></child1-comp>
  <child2-comp (click)="value=''"></child2-comp>
</div>

.

// child1-comp template:
<input type="text" [(ngModel)]="value" (keyup)="0">

.

// child2-comp template:
<ul>
  <li (click)="click.emit(text1.value)" #text1>Test</li>
  <li (click)="click.emit(text2.value)" #text2>Test2</li>
</ul>

【讨论】:

  • 通过rxjs 使用Observable 怎么样?有什么建议和优雅的例子吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-31
  • 1970-01-01
相关资源
最近更新 更多