我有一个MasterComponent,可以加载页眉,页脚,侧边栏等。在标题上有一个下拉列表,其选项在用户登录后设置。我希望标题保持不变,即使我导航到不同的加载路径不同的儿童成分。表示所选子选项不应更改,并且所有子组件都应该可以访问下拉值。在更改下拉值时,应更新/重新加载当前子组件。
我该如何处理这个问题?我想要事件监听器的功能。从MasterComponent更改模型后,重新加载当前子组件。在MasterComponent的变量变量更新中,ChildComponent将监听更新并运行某个函数或再次调用某个API并重新加载ChildComponent。
// routes
const appRoutes: Routes = [
{
path: '',
redirectTo: 'login',
pathMatch: 'full',
},
{ path: 'login', component: LoginComponent },
{ path: 'logout', component: LogoutComponent },
{
path: '',
component: MasterComponent,
canActivate: [AuthGuard],
children: [
{ path: 'record/create', component: RecordCreateComponent }, // create record for selectedRestaurant in MasterComponent
{ path: 'record/', component: RecordComponent }, // shows all record of current selectedRestaurant in MasterComponent
{ path: 'record/:id/update', component:RecordUpdateComponent }, // show form to edit record having id
{ path: 'record/:id', component: RecordComponent }, // show record details having id
]
},
{ path: '**', redirectTo: 'login' }
];
// MasterComponent
@Component({
selector: 'master',
templateUrl: templateUrl,
styleUrls:[styleUrl1]
})
export class MasterComponent implements AfterViewInit, OnInit{
restaurants: Array<Restaurant> = [];
user:User;
selectedRestaurant: Restaurant;
constructor(private router: Router, private storageHelper:StorageHelper){
}
ngAfterViewInit() {
}
ngOnInit(){
this.user = JSON.parse(this.storageHelper.getItem('user'));
this.restaurants = this.user.restaurants;
this.selectedRestaurant = this.restaurants[0];
this.router.navigate(['/record/' + this.selectedRestaurant.id]);
}
onRestaurantChange(){
this.router.navigate(['/record/' + this.selectedRestaurant.id]);
}
createRecord(){
}
}
答案 0 :(得分:26)
使用@Input
将您的数据传递给子组件,然后使用ngOnChanges
(https://angular.io/api/core/OnChanges)查看@Input
是否即时更改。
答案 1 :(得分:5)
在Angular上更新包含其模板的组件,有一个直接的解决方案,在您的ChildComponent上具有@Input
属性并添加到@Component
装饰器changeDetection: ChangeDetectionStrategy.OnPush
,如下所示:
import { ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'master',
templateUrl: templateUrl,
styleUrls:[styleUrl1],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent{
@Input() data: MyData;
}
这将完成检查输入数据是否已更改并重新渲染组件的所有工作
答案 2 :(得分:1)
更新@Vladimir Tolstikov的答案
创建一个使用ngOnChanges
的子组件。
ChildComponent.ts ::
import { Component, OnChanges, Input } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'child',
templateUrl: 'child.component.html',
})
export class ChildComponent implements OnChanges {
@Input() child_id;
constructor(private route: ActivatedRoute) { }
ngOnChanges() {
// create header using child_id
console.log(this.child_id);
}
}
现在在 MasterComponent 的模板中使用它,并将数据传递给 ChildComponent ,例如:
<child [child_id]="child_id"></child>
答案 3 :(得分:1)
以防万一,我们无法控制子组件,例如第三方库组件。
我们可以使用*ngIf
和setTimeout
从父级重置子级组件,而无需更改子级组件。
.template:
.ts:
show:boolean = true
resetChildForm(){
this.show = false;
setTimeout(() => {
this.show = true
}, 100);
}
答案 4 :(得分:0)
您可以将@input与ngOnChanges结合使用,以查看发生的更改。
参考: https://angular.io/api/core/OnChanges
(或)
如果要在多个组件或路由之间传递数据,请使用Rxjs方式。
Service.ts
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class MessageService {
private subject = new Subject<any>();
sendMessage(message: string) {
this.subject.next({ text: message });
}
clearMessages() {
this.subject.next();
}
getMessage(): Observable<any> {
return this.subject.asObservable();
}
}
Component.ts
import { Component, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { MessageService } from './_services/index';
@Component({
selector: 'app',
templateUrl: 'app.component.html'
})
export class AppComponent implements OnDestroy {
messages: any[] = [];
subscription: Subscription;
constructor(private messageService: MessageService) {
// subscribe to home component messages
this.subscription = this.messageService.getMessage().subscribe(message => {
if (message) {
this.messages.push(message);
} else {
// clear messages when empty message received
this.messages = [];
}
});
}
ngOnDestroy() {
// unsubscribe to ensure no memory leaks
this.subscription.unsubscribe();
}
}