Skip to content

Update view when object has been pushed into array in Angular

I have an array of objects, I have added a click handler to manual test pushing an item into that array, It does that successfully, but what it does not do is update the view based on this. Do I need to put the method in the ngOnit? What I have so far just makes the object appear not based the click handler.

Code so far would be:

public times = [
    {
      id: 1,
      title: "Here and now",
      start: new Date("2021-01-27T09:00:00"),
      end: new Date("2021-01-27T09:30:00"),
    },
    {
      id: 12,
      title: "Here and now 2",
      start: new Date("2021-01-27T11:00:00"),
      end: new Date("2021-01-27T12:30:00"),
    }
  ];

public pushArray() {
    this.times.push({
      id: 3,
      title: "Again title",
      start: new Date("2021-02-02T10:00:00"),
      end: new Date("2021-02-02T12:30:00"),
    });
    console.log(this.times);
  }

  public addClickHandler() {
    this.pushArray();
  }

  ngOnInit() {
    this.pushArray();
  }

Binded to

<button class="mr-3" (click)="addClickHandler()">
Add </button>

But this works in the way of the object appearing already, not based on the click? I know putting the this.pushArray() into the ngOnit is not correct but just wanted to check it works and appears as it should if the user clicked and adde the item.

Answer

Even though the array’s content changed, the view is not updated because the times array has not changed from Angular’s change detection perspective, as the array is still in the same memory address (an array variable is a actually a reference). The solution is to reassign the array, thus changing its reference (“relocating” it to a different memory address) and trigger change detection. Like this:

public pushArray() {
    this.times.push({
      id: 3,
      title: "Again title",
      start: new Date("2021-02-02T10:00:00"),
      end: new Date("2021-02-02T12:30:00"),
    });
    this.times = [...this.times]; // <== this is the trigger
    console.log(this.times);
  }

For the same reason, in simple Typescript, you can do the following:

const a = [1, 2, 3, 4];
a.push(5);  // <== you can add elements to const array because you don't change its address

But you can’t do:

const a = [1, 2, 3, 4];
a = [1, 2, 3, 4, 5];  // <== the compiler will throw an error, because its address changes

and instead do:

let a = [1, 2, 3, 4];
a = [1, 2, 3, 4, 5];  // <== this will work