web-dev-qa-db-ja.com

angular 2:サービスを使用してイベントをブロードキャストする

あるコンポーネントでボタンをクリックして、別のコンポーネントの要素にフォーカスしようとしています。 (率直に言って、なぜこれがそんなに複雑なのか理解できませんが、実際に動作するもっと簡単な方法を実装することはできませんでした。)

サービスを使用しています。 thatクリックが発生したことを除いて、データを渡す必要はありません。リスニングコンポーネントがイベントにどのように応答するかはわかりません。

app.component:

メインコンテンツにスキップ

import { Component } from '@angular/core';
import { SkipToContentService } from './services/skip-to-content.service';


export class AppComponent {
    constructor(
        private skipToContent: SkipToContentService
    ) {}
    }

    skipLink() {
        this.skipToContent.setClicked();
    }

}

ログインコンポーネント:

<input type="text" name="username" />


import { Component, OnInit } from '@angular/core';
import { SkipToContentService } from '../../../services/skip-to-content.service';

export class BaseLoginComponent implements OnInit {

    constructor(
        private skipToContent: SkipToContentService
        ) {
    }

    ngOnInit() {
        this.skipToContent.skipClicked.subscribe(
            console.log("!")
            // should put focus() on input
        );

    }
}

skip-to-content.service:

import { Injectable, EventEmitter } from '@angular/core';

@Injectable()
export class SkipToContentService {

    skipClicked: EventEmitter<boolean> = new EventEmitter();


    constructor() {
    }

    setClicked() {
        console.log('clicked');
        this.skipClicked.emit();
    };
}

ここでは、skipClickedイベントをログオンが「聞く」方法について少し迷っています。

18
DaveC426913

SetClicked()メソッドを少し変更するだけです:

this.skipClicked.next(true);

this.skipClicked.emit();の代わりに

サブスクリプションを次のように変更します。

this.skipToContent.skipClicked.subscribe( value => {
    if (value === true) {
        console.log("!"); 
        // should put focus() on input 
    }
});

これで問題が解決します。

14
Faisal

EventEmitterは、@ Outputディレクティブを持つ実際のコンポーネントでのみ使用する必要があります。今後、他の機能は動作しない可能性があります。

子と親のコミュニケーションには、SubjectまたはBehaviorSubjectを使用することをお勧めします。これはangularガイドからの例です。

https://angular.io/guide/component-interaction

_@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);
  }
}
_

先端:

何かが発生または完了したことを示すイベントがあり、実際のデータが関連付けられていない場合は、Subject<void>()を使用できます。これにより、next()の署名がクリーナーになり、そのためにダミー値を指定する必要がなくなります。

例えば。

_windowClosed = new Subject<void>();
_

windowClosed.next()はイベントを発行します

11
Simon_Weaver