Angular 2: использование службы для трансляции события
Я пытаюсь получить щелчок кнопки в одном компоненте, чтобы сосредоточить внимание на элементе на другом компоненте. (Честно говоря, я не понимаю, почему это должно быть настолько сложно, но я не смог реализовать какой-либо более простой способ, который действительно работает.)
Я использую услугу. Ему не нужно передавать какие-либо данные, кроме того, что произошел щелчок. Я не уверен, как компонент прослушивания должен реагировать на событие.
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
);
}
}
пропуск к 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.
Ответы
Ответ 1
Прежде всего, используйте BehaviorSubject
вместо EventEmitter
. Измените объявление skipCliekd
следующим:
skipClicked: BehaviorSubject<boolean> = new BehaviorSubject(false);
Затем вам нужно передать новое значение, используя метод next()
следующим образом:
this.skipClicked.next (true);
Также измените подписку на:
this.skipToContent.skipClicked.subscribe( value => {
if (value === true) {
console.log("!");
// should put focus() on input
}
});
Ответ 2
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()
отправит событие