简体   繁体   中英

Angular Parent-Child Component: Load Child on Parent click

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();
  }
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM