【问题标题】:Reload child component when variables on parent component changes. Angular2当父组件上的变量发生变化时重新加载子组件。角2
【发布时间】:2017-03-08 12:02:32
【问题描述】:

我有一个 MasterComponent,它加载页眉、页脚、侧边栏等。在页眉上有一个下拉菜单,一旦用户登录,它的选项就会设置。我希望页眉保持不变,即使我导航到加载的不同路线不同的子组件。意味着所选选项不应更改,并且下拉列表的值应可在所有子组件中访问。 Onchange of dropdown value 当前子组件应该被更新/重新加载。

我应该如何解决这个问题?我想要事件监听器类型的功能。一旦 MasterComponent 中的模型发生变化,重新加载当前子组件。在 MasterComponent 的变量变量 update 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(){
    }
}

【问题讨论】:

  • 该问题的主题具有误导性“更改子组件而不重新加载父组件”。你只需要正确设置你的路由器。这似乎不是父 子问题。
  • @jmachnik 我想从子组件访问父变量,反之亦然。并且父组件值应该在所有路由中保持一致。

标签: angular


【解决方案1】:

使用@Input 将您的数据传递给子组件,然后使用ngOnChanges (https://angular.io/api/core/OnChanges) 查看@Input 是否即时更改。

【讨论】:

  • 当我向输入发送相同的值时,这是否有效??
  • @AbhishekEkaanth 不确定,检查一下。但如果它基于setter,我认为“是”,但如果你通过引用手动设置它,不应该发生在模板中。
  • 它不是基于 setters。但我将值更改为零并传递了正确的值但它不起作用
  • @AbhishekEkaanth 那么你做错了什么......检查示例,简化你的组件并调试。
【解决方案2】:

@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】:

    在 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;
    }
    

    这将完成检查输入数据是否已更改并重新渲染组件的所有工作

    【讨论】:

    • 它工作正常。但是如果想重新加载子组件怎么做,我必须调用 ngOnInit 方法?
    • 从使用 ChangeDetectionStrategy.OnPush 的组件中,所有依赖于 @Input() 的子组件都会更新
    • @CarlosE 您只是在停用更改检测。那应该如何重新加载子组件? Afaik 唯一可行的解​​决方案是通过实现 onChanges 手动更新子组件。
    【解决方案4】:

    如果我们无法控制子组件,例如 3rd 方库组件。

    我们可以使用*ngIfsetTimeout 从父组件中重置子组件,而无需对子组件进行任何更改。

    .模板:

    <child-component *ngIf="show"></child-component>
    <button (click)="resetChildForm()"></button>
    

    .ts:

    show:boolean = true
    
    resetChildForm(){
       this.show = false;
    
       setTimeout(() => {
          this.show = true
        }, 100);
    }
    

    【讨论】:

      【解决方案5】:

      您可以将@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();
        }
      }
      

      参考:http://jasonwatmore.com/post/2019/02/07/angular-7-communicating-between-components-with-observable-subject

      【讨论】:

        【解决方案6】:

        要触发 LIST/ARRAY ngOnChanges 使用 this.arr = [].concat(this.arr);

        【讨论】:

          猜你喜欢
          • 2021-07-09
          • 1970-01-01
          • 2020-02-27
          • 1970-01-01
          • 2022-11-26
          • 2021-06-25
          • 2017-06-04
          • 2018-06-29
          • 2022-06-30
          相关资源
          最近更新 更多