John Shelby
John Shelby

Reputation: 102

New content now showing up when added (angular)

I have the app.component, the post-create.component and the post-list.component . the app.component.html looks like this: app.component.html

<app-header></app-header>
<main>
<app-post-create (postCreated)="onAddedPost($event)" ></app-post-create>
<app-post-list [posts]="storedPosts" ></app-post-list>
</main>

the post-list.component.ts looks like this post-list.component.ts

import { Component, Input } from '@angular/core';
import { Post } from '../post'
@Component({
  selector: 'app-post-list',
  templateUrl: './post-list.component.html',
  styleUrls: ['./post-list.component.css']
})
export class PostListComponent  {

  @Input() posts:Post[] = [];

}

the post-create.component.ts looks like this post-create.component.ts

import { sharedStylesheetJitUrl } from '@angular/compiler';
import { Component, EventEmitter, Injectable, Output, OutputDecorator } from '@angular/core';
import { Post } from '../post'
@Component({
  selector: 'app-post-create',
  templateUrl: './post-create.component.html',
  styleUrls: ['./post-create.component.css']
})
export class PostCreateComponent {
  enteredContent='';
  enteredTitle='';
  @Output() postCreated: EventEmitter<Post> = new EventEmitter<Post>();
  onAddPost(){
    const post={title:this.enteredTitle,content:this.enteredContent};
    this.postCreated.emit(post);
  }
}

and the app.component.ts looks like this app.component.ts

import { Component, Output,Input } from '@angular/core';
import { Post } from '../app/posts/post';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],

})
export class AppComponent {
  storedPosts: Post[] = [];
  onAddedPost(post:Post){
    this.storedPosts.push(post);
  }
 }

the problem is that when I press add post it wont show the new post. any ideas? edit: also my post.create.component.html looks like this post.create.component.html

<mat-card>
  <mat-form-field>
    <input matInput type="text" [(ngModel)]="enteredTitle">
  </mat-form-field>
  <mat-form-field>
  <textarea matInput rows="6" [(ngModel)]="enteredContent"></textarea>
  </mat-form-field>
  <button mat-raised-button
  (click)="onAddPost()">Save post!</button>
  </mat-card>

and the post-list.component.html looks like this:

<mat-accordion multi="true" *ngIf="posts.length>0" >
  <mat-expansion-panel *ngFor="let post of posts">
    <mat-expansion-panel-header>
      {{post.title}}
    </mat-expansion-panel-header>
        {{post.content}}
  </mat-expansion-panel>
</mat-accordion>
<p class="mat-body-1" *ngIf="posts.length <=0">no posts added yet</p>

Upvotes: 0

Views: 114

Answers (3)

Arun Manandhar
Arun Manandhar

Reputation: 1

Try

onPostAdded(posts) {

this.Storedposts.push(posts)

}

instead of

onPostAdded(post) {

this.Storedposts.push(post)

}

Upvotes: -1

Barremian
Barremian

Reputation: 31115

Angular's @Input would only recognize the changes to it's variables if the underlying reference has been adjusted. Since the Array#push doesn't affect it's holding variable, they might not be detected. Instead of Array#push you could append new elements using the spread syntax.

Try the following

onAddedPost(post:Post){
  this.storedPosts = [...this.storedPosts, post];
}

Check @Input change using ngOnChanges() hook

You could check if the changes are detected in the child component using the ngOnChanges hook. Try the following

import { Component, Input, OnChanges, SimpleChanges } from "@angular/core";
import { Post } from "../post";
@Component({
  selector: "app-post-list",
  templateUrl: "./post-list.component.html",
  styleUrls: ["./post-list.component.css"]
})
export class PostListComponent implements OnChanges {
  @Input() posts: Post[] = [];

  ngOnChanges(changes: SimpleChanges) {
    if (changes.posts && changes.posts.currentValue) {
      console.log(changes.posts.currentValue);
    }
  }
}

I've modified your Stackblitz.

Upvotes: 2

AliF50
AliF50

Reputation: 18859

I think this has to do with change detection and that arrays are reference types so you have to change the location in memory that the array is stored in order for change detection to be guaranteed to run.

import { Component, Output,Input } from '@angular/core';
import { Post } from '../app/posts/post';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],

})
export class AppComponent {
  storedPosts: Post[] = [];
  onAddedPost(post:Post){
    // the line below does not change the location of the array in memory and 
    // therefore change detection doesn't run
    // this.storedPosts.push(post);  
    // update this way, spread the old posts and append the new post
    // and this will assign storedPosts in a new location in the array.
    this.storedPosts = [...this.storedPosts, post];
  }
 }

Upvotes: 1

Related Questions