【问题标题】:Angular Parent-Child Component: Load Child on Parent clickAngular父子组件:在父单击时加载子项
【发布时间】:2018-10-16 00:59:29
【问题描述】:

我有文章列表和文章详细信息组件。

文章列表: ——文章列表。作为表格加载到 html 中。处理点击事件并设置文章ID -- 使用文章 id 属性向文章详细信息发送信号以作为@Input 属性加载。

文章详情: -- @Input 属性从列表中侦听并注册 ng-OnChange 事件以处理任何更改 -- 加载文章详细视图模型(带有更多细节) -- 使用 Reactive Form 加载所有属性以纠正 formgroup。 -- 使用示例属性并在 UI 中显示带有 Reactive 表单属性,只是为了知道 @Input 属性从列表中获取正确的值。

现在,我在 Sample 属性中得到了正确的值。并且服务方法也从文章详细信息更改事件中调用。它还设置了视图模型。但是这里的问题,查看显示一键旧数据。

如果我单击第二篇文章,我的示例属性会正确更新,这证明,我的详细信息组件会获取信息,最终视图模型也会在服务响应后更新。但 View 显示旧的 View Model。

每次点击最后存储的视图模型数据都会显示在视图上。知道为什么吗? 这是代码:

 **#Article-List Component.ts**   
 @Component({
     selector: 'admin-article-list',
     templateUrl: './article-list.component.html',
     styleUrls: ['./article-list.component.css']
 })
 export class ArticleListComponent extends BaseImplementationComponent {
     public selectedArticleId: string;

     articleClick(event: Event, articleViewModel: ArticleViewModel) {
         this.selectedArticleId = articleViewModel.articleId;
     }
 }

 **#Article-List-Html**
 <div *ngFor="let article of articles">
    <div class="row article" (click)="articleClick($event, article)">
       <div class="col-xs-3 col-sm-3">
          <a href='{{article.articleId}}'>{{article.articleId}}</a>
       </div>
    </div>
    <div>
       <admin-article-detail *ngIf="isReadyToLoad" [articleId]="selectedArticleId"></admin-article-detail>
    </div>
 </div>

 **#Article-Detail-Component.ts**
 @Component({
    selector: 'admin-article-detail',
    templateUrl: './article-detail.component.html',
    styleUrls: ['./article-detail.component.css']
 })
 export class ArticleDetailComponent extends BaseImplementationComponent {
    @Input()
    articleId: string;

    articleViewModel: ArticleViewModel;
    articleDetailFormGroup: FormGroup;

    constructor(private formBuilder: FormBuilder, private articleService: ArticleService) {super();

    this.createArticleDetailForm();
   }

    protected ngOnChangesAtBaseComponent(): void {
       this.loadArticleDetail();
       this.patchArticleDetailForm();
       this.articleIdComingfromParent = this.articleId;
    }

    private loadArticleDetail() {
       this.articleService.getArticle(this.articleId)
       .map(item => this.articleViewModel = item)
       .subscribe(
       (item) => {
          console.log(item);
          this.articleViewModel = item;
       },
       (err) => {
          console.log(err);
       });
    }

    private patchArticleDetailForm() {
       //console.log(this.articleViewModel.articleTitle);
       this.articleDetailFormGroup.get('articleBasicDetail').patchValue({ 
       articleTitle: this.articleViewModel.articleTitle });
    }

    private createArticleDetailForm() {
        this.articleDetailFormGroup = this.formBuilder.group({
           articleBasicDetail: this.formBuilder.group({
           articleTitle: ''
           })
        });
    }
 }


 **#Article-Detail-Html**
 <form class="form-horizontal" [formGroup]="articleDetailFormGroup">
    <div class="form-group" formGroupName="articleBasicDetail">
       <div class="col-sm-12">
          <label for="articleTitle" class="center-block">Street:
             <input type="text" id="articleTitle" class="form-control" formControlName="articleTitle">
             Updated from: {{articleIdComingfromParent}}
          </label>
       </div>
    </div>
</form>

【问题讨论】:

    标签: angular angular-components


    【解决方案1】:

    我认为如果输入的引用发生变化,子组件会触发变化,你有这个错误是因为你直接改变了输入,这里有一个解决方案,使用 OnPush 检测策略和 doCheck

     @Component({
      selector: 'admin-article-detail',
      templateUrl: './article-detail.component.html',
      styleUrls: ['./article-detail.component.css'],
      changeDetection: ChangeDetectionStrategy.OnPush
     })
     @Input() articleId: string;
     selectedArticle : string; // create this new property and use it 
    
     constructor(private cd: ChangeDetectorRef) {}
    
     ngOnInit() { this.selectedArticle = this.articleId;  }
    
     ngDoCheck() {
      if (this.selectedArticle !== this.articleId) {
          this.selectedArticle = this.articleId;
          this.cd.markForCheck();
      }
     }
    

    【讨论】:

    • 嗨 Fateh,这是处理这种情况的正确方法还是我正在做一些奇怪的事情?此外,如果这是处理此点击的正确方法,谁将调用 ngDoCheck 以及如何调用?
    • 还有一件事:如果我们在这个组件中也有 ngOnChanges 事件并且我们标记 this.cd.markForCheck() 那么这个 ngOnChange 也会一次又一次地调用?
    • 好吧,如果输入参考没有改变,改变检测将不起作用,所以我们必须手动使用 DoCheck 和 markForCheck 来通知 angular。检查blog.angular-university.io/onpush-change-detection-how-it-works,他们有一个示例,他们更改了输入引用以使其工作
    猜你喜欢
    • 2017-05-13
    • 2020-08-23
    • 2017-11-20
    • 2013-11-28
    • 2023-03-13
    • 2019-05-06
    • 2019-08-07
    • 1970-01-01
    • 2017-04-05
    相关资源
    最近更新 更多