我有一个父组件进入服务器并获取一个对象。
// parent component
@Component({
selector : 'node-display',
template : `
<router-outlet [node]="node"></router-outlet>
`
})
export class NodeDisplayComponent implements OnInit {
node: Node;
ngOnInit(): void {
this.nodeService.getNode(path)
.subscribe(
node => {
this.node = node;
},
err => {
console.log(err);
}
);
}
在(孩子中的一个)我的孩子展示
export class ChildDisplay implements OnInit{
@Input()
node: Node;
ngOnInit(): void {
console.log(this.node);
}
}
它似乎并不像我认为我可以将数据注入路由器插座。看起来我在Web控制台中收到了错误...
Can't bind to 'node' since it isn't a known property of 'router-outlet'.
这有点道理,但我怎么做以下......
1) Grab the "node" data from the server, from within the parent component
2) Pass the data I have retrieved from the server into the child router-outlet
看起来路由器插座的工作方式并不相同。
唯一的方法是使用共享服务。
<router-outlet [node]="..."></router-outlet>
只是无效。路由器添加的组件作为兄弟添加到<router-outlet>
并且不替换它。
另见https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service
@Injectable()
export class NodeService {
private node:Subject<Node> = new BehaviorSubject<Node>([]);
get node$(){
return this.node.asObservable().filter(node => !!node);
}
addNode(data:Node) {
this.node.next(data);
}
}
@Component({
selector : 'node-display',
providers: [NodeService],
template : `
<router-outlet></router-outlet>
`
})
export class NodeDisplayComponent implements OnInit {
constructor(private nodeService:NodeService) {}
node: Node;
ngOnInit(): void {
this.nodeService.getNode(path)
.subscribe(
node => {
this.nodeService.addNode(node);
},
err => {
console.log(err);
}
);
}
}
export class ChildDisplay implements OnInit{
constructor(nodeService:NodeService) {
nodeService.node$.subscribe(n => this.node = n);
}
}
Günters的答案很棒,我只想指出不使用Observables的另一种方法。
这里我们必须记住这些对象是通过引用传递的,所以如果你想对子对象做一些工作并且不影响父对象,我建议使用Günther的解决方案。但如果无关紧要,或者实际上是期望的行为,我建议如下。
@Injectable()
export class SharedService {
sharedNode = {
// properties
};
}
在您的父级中,您可以分配值:
this.sharedService.sharedNode = this.node;
在您的孩子(和父母)中,在构造函数中注入共享服务。如果您希望在该模块中的所有组件上都使用单件服务,请记住在模块级提供程序数组中提供服务。或者,只需在父级的providers数组中添加服务,然后父级和子级将共享相同的服务实例。
node: Node;
ngOnInit() {
this.node = this.sharedService.sharedNode;
}
正如纽曼亲切地指出的那样,你也可以在html模板或getter中使用this.sharedService.sharedNode
:
get sharedNode(){
return this.sharedService.sharedNode;
}
import {Injectable, EventEmitter} from "@angular/core";
@Injectable()
export class DataService {
onGetData: EventEmitter = new EventEmitter();
getData() {
this.http.post(...params).map(res => {
this.onGetData.emit(res.json());
})
}
import {Component} from '@angular/core';
import {DataService} from "../services/data.service";
@Component()
export class MyComponent {
constructor(private DataService:DataService) {
this.DataService.onGetData.subscribe(res => {
(from service on .emit() )
})
}
//To send data to all subscribers from current component
sendData() {
this.DataService.onGetData.emit(--NEW DATA--);
}
}
有三种方法可以将数据从Parent传递给Children
this.data = this.route.snaphsot.data['dataFromResolver'];
this.data = this.route.parent.snaphsot.data['dataFromResolver'];
注1:你可以阅读有关解析器here的信息。还有一个解析器示例以及如何将解析器注册到模块中,然后将解析器中的数据检索到组件中。父母和孩子的解析器注册是相同的。
注意2:您可以阅读有关ActivatedRoute here的信息,以便能够从路由器获取数据
在this问题之后,在Angular 7.2中,您可以使用历史状态将数据从父级传递给子级。所以你可以做点什么
发送:
this.router.navigate(['action-selection'], { state: { example: 'bar' } });
检索:
constructor(private router: Router) { console.log(this.router.getCurrentNavigation().extras.state.example); }
但要小心保持一致。例如,假设您要使用路由器插座在左侧栏上显示列表,在右侧显示所选项目的详细信息。就像是:
项目1(x)| ..............................................
项目2(x)| ......选择项目详情.......
项目3(x)| ..............................................
项目4(x)| ..............................................
现在,假设您已经点击了一些项目。单击浏览器后退按钮将显示上一项的详细信息。但是,如果您同时点击(x)并从列表中删除该项目,该怎么办?然后执行后退单击,将显示已删除项目的详细信息。