仅是我的问题的一个示例:- 父母有孩子1和孩子2。
我正在数组child2的onLoad中显示月份列表。
在child1上单击按钮,将按一次弹出几个月。
在child1上单击一个按钮,它将向父级发送新值,并且该值将从父级发送到child2.ts并更新月份的数组
问题是,从父级到子级2的通信时出现错误。 我使用了可观察的订阅方法,它显示为
this.months.asObservable is not a function
下面是我的代码。
////////////////child1.ts///////////////////////////////////
onClick() {
this.navigateMonths.emit(this.month);
}
////////////// parent.ts//////////////////////
months: Subject < void > = new Subject < void > ();
navigatedMonths(months) {
this.months = months;
this.months.asObservable();
}
/////////child2.ts////////////////////////
@Input() navigatedMonths: Observable < void > ;
ngOnInit() {
this.navigatedMonths.subscribe((months) => {
this.months = months;
})
this.getMonths(this.year, this.month);
}
////////////// parent.html//////////////////////////////////////////
< child2 class="row-items" [navigatedMonths]="months">< /child2>
< child1(navigateMonths)='navigatedMonths($event)'> Next Month< /child1>
答案 0 :(得分:1)
快速修正-摆脱不需要的可观察对象/主题
////////////// parent.ts//////////////////////
months: any[]; // no subject anymore
navigatedMonths(months) {
this.months = months;
}
/////////child2.ts////////////////////////
@Input()
set navigatedMonths(months: any[]) { // make a setter from your input
// Do whatever you want when new months come in
}
您可能应该考虑引入两个孩子之间共享的服务。父母不必知道这几个月。
阅读:https://angular.io/guide/component-interaction(父母和子女通过服务进行沟通)-组件之间的通信同样适用(即使他们没有父母与孩子的关系)
该服务可能如下所示:
export class MonthsService {
// private for internal use
private monthsSource: BehaviorSubject<string[]> = new BehaviorSubject([]); // init with empty array
// public for use in components or other services
months$: Observable<string[]> = this.monthsSource.asObservable();
addMonth(newMonth: string) {
const months = [...this.monthsSource.getValue(), newMonth]; // Create new months array
this.monthsSource.next(months);
}
}
完整示例:https://stackblitz.com/edit/ng-zorro-antd-start-ddozvn
现在,子级不再有输入或输出,父级组件保持干净。每个对数据感兴趣的组件都只订阅了可观察的months $。
答案 1 :(得分:1)
您提到的场景可以通过从child1 to parent
发出数据(使用eventEmitters)来实现
child1.ts
i = 0;
months = ["jan","feb","march","april"];
@Output() messageEvent = new EventEmitter<string>();
sendMessage() {
this.messageEvent.emit(this.months[this.i]);
this.i++;
}
,然后从parent to child2
(使用@viewChild)。
parent.ts
message:string;
@ViewChild(Child2Component) child;
receiveMessage($event) {
this.message = $event
this.child.addMonth(this.message);
}
child2.ts
months:any[] = [];
@Input() childMessage: string;
addMonth(month){
this.months.push(month);
console.log(this.months);
}
添加了工作演示:demo
注意:可以在控制台上看到child2的months数组的输出。
编辑:以下是在Subject
中使用service
的第二种方法。此方法可用于所有类型的组件交互。无论是parent-child
还是child-parent
或siblings
交互。
您应遵循以下步骤:
myService.ts
创建正在使用的主题。 (主题需要从rxjs导入)
mySubject = new Subject();
child1.ts
使用next()
向主体添加/推送项目:
this.myService.mySubject.next(this.months[this.i++])
child2.ts
订阅主题以阅读该项目:
ngOnInit(){
this.myService.mySubject.subscribe((data)=>{
this.months.push(data);
console.log(this.months);
});
}
答案 2 :(得分:0)
另一种选择是对@Input()
,@Output()
和EventEmitter
使用双向绑定。通过将@Output()
EventEmitter
命名为与@Input()
相同的名称,并在名称后附加Change
,可以实现双向绑定。
@Input()
public message: Message;
@Output()
public messageChange: EventEmitter<Message> = new EventEmitter<Message>();
public text: string;
send() {
if (this.text.trim().length > 0) {
this.messageChange.emit(new Message(`Child1: ${this.text}`));
}
}
<app-child1 [(message)]="message"></app-child1>
<app-child2 [(message)]="message"></app-child2>
https://stackblitz.com/edit/angular-46ndlt
https://medium.com/@preethi.s/angular-custom-two-way-data-binding-3e618309d6c7