Angular 父子组件:在父级单击时加载子级 [英] Angular Parent-Child Component: Load Child on Parent click

查看:47
本文介绍了Angular 父子组件:在父级单击时加载子级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

文章详情:-- @Input 属性从列表中监听并注册 ng-OnChange 事件以处理任何更改-- 加载文章详细视图模型(有更多详细信息)-- 使用 Reactive Form 将所有属性加载到正确的表单组中.-- 使用示例属性并通过响应式表单属性在 UI 中显示只是为了知道 @Input 属性正在从列表中获取正确的值.

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

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

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

 **#Article-List Component.ts**@成分({选择器:'管理文章列表',templateUrl: './article-list.component.html',styleUrls: ['./article-list.component.css']})导出类 ArticleListComponent 扩展 BaseImplementationComponent {公共selectedArticleId:字符串;文章点击(事件:事件,文章视图模型:文章视图模型){this.selectedArticleId = articleViewModel.articleId;}}**#文章列表-HTML**<div *ngFor="让文章的文章"><div class="row article" (click)="articleClick($event, article)"><div class="col-xs-3 col-sm-3"><a href='{{article.articleId}}'>{{article.articleId}}</a>

<div><admin-article-detail *ngIf="isReadyToLoad" [articleId]="selectedArticleId"></admin-article-detail>

**#Article-Detail-Component.ts**@成分({选择器:管理文章详细信息",templateUrl: './article-detail.component.html',styleUrls: ['./article-detail.component.css']})导出类 ArticleDetailComponent 扩展 BaseImplementationComponent {@输入()文章ID:字符串;文章视图模型:文章视图模型;articleDetailFormGroup:FormGroup;构造函数(私有表单构建器:FormBuilder,私有文章服务:文章服务){super();this.createArticleDetailForm();}受保护的 ngOnChangesAtBaseComponent(): void {this.loadArticleDetail();this.patchArticleDetailForm();this.articleIdComingfromParent = this.articleId;}私人 loadArticleDetail() {this.articleService.getArticle(this.articleId).map(item => this.articleViewModel = item).订阅((项目) =>{控制台日志(项目);this.articleViewModel = item;},(错误) =>{控制台日志(错误);});}私人补丁ArticleDetailForm(){//console.log(this.articleViewModel.articleTitle);this.articleDetailFormGroup.get('articleBasicDetail').patchValue({文章标题:this.articleViewModel.articleTitle });}私有 createArticleDetailForm() {this.articleDetailFormGroup = this.formBuilder.group({articleBasicDetail: this.formBuilder.group({文章标题:''})});}}**#文章-详细信息-HTML **<form class="form-horizo​​ntal" [formGroup]="articleDetailFormGroup"><div class="form-group" formGroupName="articleBasicDetail"><div class="col-sm-12"><label for="articleTitle" class="center-block">街道:<input type="text" id="articleTitle" class="form-control" formControlName="articleTitle">更新自:{{articleIdComingfromParent}}

</表单>

解决方案

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

 @Component({选择器:管理文章详细信息",templateUrl: './article-detail.component.html',styleUrls: ['./article-detail.component.css'],changeDetection: ChangeDetectionStrategy.OnPush})@Input() 文章ID:字符串;selectedArticle : 字符串;//创建这个新属性并使用它构造函数(私有 CD:ChangeDetectorRef){}ngOnInit() { this.selectedArticle = this.articleId;}ngDoCheck() {如果 (this.selectedArticle !== this.articleId) {this.selectedArticle = this.articleId;this.cd.markForCheck();}}

I have article list and article detail component.

Article List: -- list of articles. load into html as a table. handled a click event and set the article id -- use the article id property to send a signal to article detail to load as @Input property.

Article Detail: -- @Input property listen from list and register ng-OnChange event to handled any change -- Load the article detail view model (with more detail) -- Use Reactive Form to load all the property to correct formgroup. -- Use sample property and display in UI with Reactive form property just to know the @Input property is getting the correct value from list.

Now, I am getting correct value in Sample property. and also the service method is getting called from Article Detail change event. It also set the view model. but the problem here, View display one click old data.

If I click the second article, my sample property updates correctly which proves that, my detail component gets the information and eventually view model also gets updated after service response. but View display the old View Model.

Every click last stored viewmodel data is getting display on View. any idea why? Here is code:

 **#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>

解决方案

i think the child component will trigger changes if the reference of the input changes, you have this error because you are changing the input directly, here is a solution for you, using OnPush detection strategy and 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();
  }
 }

这篇关于Angular 父子组件:在父级单击时加载子级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆