The View does not get updated by Angular's *ngFor directive

When I modify the Array of servers from outside the class declaration, the View/HTML component does not update accordingly. However, when I perform the same modification from inside the class, it works fine. Both functions successfully update the servers Array, but only the inner function triggers the DOM update. Please refer to the following code ->

export class ContentComponent implements OnInit {

  cdr: ChangeDetectorRef;
  
   @Input() servers: Server[] = [];

   constructor( cdr: ChangeDetectorRef) {
    this.cdr = cdr;
   }

   addServerToServerListInsideClass() { //This is the working test function
    this.servers.push(new Server("test", "test"));
   }

  ngOnInit(): void {
  }
}

export function addServerToServerList(contentComponent: ContentComponent, name: string, content: string) {
  const newServer = new Server(name, content);
  contentComponent.servers.push(newServer);
  contentComponent.servers.forEach(element => {
    console.log(element)
  });
  contentComponent.cdr.markForCheck();
}

Here is the template with the *ngFor loop->

<button (click)="addServerToServerListInsideClass()">My Button</button> <!-- testing inside a function-->
<div *ngFor="let server of servers | keyvalue">
    <app-content-item [key]="server.key" [value]="server.value"></app-content-item>
</div>

The exported function defined outside the class declaration is called in another .ts file. Please refer to the code below ->

export class EingabeComponent implements OnInit {

  serverName!: string; 
  serverContent!: string;

  constructor(public contentComponent: ContentComponent) { 
  }

  onUpdateServerName(event: Event) {
    const target = event.target as HTMLInputElement;
    this.serverName =  target.value;
  }

  onUpdateServerContent(event: Event) {
    const target = event.target as HTMLInputElement;
    this.serverContent = target.value;
  }

  onCreateServer() {
    addServerToServerList(this.contentComponent, this.serverName, this.serverContent);
  }

  ngOnInit(): void {
  }

}

The onCreateServer() function is invoked within the following template:

<div class="row">
    <div class="col-md-6">
        <h1>Add new Server or blueprints</h1>
        <label for="name">Server Name</label>
        <input
            type="text" name="name"
            (input)="onUpdateServerName($event)">

         <label for="content">Server Content</label>
         <input
            type="text" name="content"
            (input)="onUpdateServerContent($event)">

        <button class="btn btn-primary"
        (click)="onCreateServer()">Add Server
         Add Server </button>
    </div>                       
</div>

Thank you for your assistance! :)

Answer №1

Implementing ngOnChanges to detect changes in Angular

import { Component, OnInit, OnChanges, SimpleChanges } from '@angular/core';

export class ContentComponent implements OnInit, OnChanges  {

  cdr: ChangeDetectorRef;
  
   @Input() servers: Server[] = [];

   constructor( cdr: ChangeDetectorRef) {
    this.cdr = cdr;
   }

   addServerToServerListInsideClass() { //A custom test function
    this.servers.push(new Server("test", "test"));
   }

  ngOnInit(): void {
  }

  ngOnChanges(changes: SimpleChanges) {
    console.log(changes)
    // If there are changes and it's not the first change ---> update this.servers variable with new data from changes.servers.
  }
}

Answer №2

Perhaps it's unclear if I fully grasp your issue, but in case you possess a functional component that operates successfully when addServerToServerListInsideClass() is executed and wish to run that method from a separate .ts file, simply establish a ViewChild to trigger it:

  @ViewChild(AlternateComponent, { static: true })
  alternateComponent!: AlternateComponent;

then initiate it as follows:

alternateComponent.executeAdditionToServerList();

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips on Importing a Javascript Module from an external javascript file into an <script> tag within an HTML file

I'm facing an issue while attempting to import the 'JSZip' module from an external node package called JSZip in my HTML File. The usual method of importing it directly using the import command is not working: <script> import ...

Using Angular 4: Redirecting Menu to Component with Electron

I am currently working on my first project using Angular 4 and Electron to develop a desktop application. One of the challenges I'm facing is figuring out how to redirect to a specific component when a submenu item is clicked after overriding the ele ...

Angular 2+: Harnessing the Power of Web Tokens

After sending a POST request to the backend REST API through a login component, I receive an x-auth token in the response headers. What is the best way to retrieve and save this token for using it in all subsequent API requests throughout the user's l ...

Conversion of UTC timestamp to a timestamp in the specified timezone

this.selectedTimezone="Pacific/Kiritimati"; //this value will come from a dropdown menu These records represent the data.body returned by an API call. Iterating through each record in the dataset: { We are creating a new Date object based on the ...

Best practices for implementing "Event Sourcing" in the NestJS CQRS recipe

I've been exploring the best practices for implementing "Event Sourcing" with the NestJS CQRS recipe (https://docs.nestjs.com/recipes/cqrs). After spending time delving into the features of NestJS, I have found it to be a fantastic framework overall. ...

Struggling to find the definition of a Typescript decorator after importing it from a separate file

Consider the following scenario: decorator.ts export function logStuff(target: Object, key: string | symbol, descriptor: TypedPropertyDescriptor<any>) { return { value: function (...args: any[]) { args.push("Another argument ...

Preventing Page Refresh when Button is Clicked in Angular

How can I prevent page reload when a button is clicked in Angular? I'm developing a quiz application in Angular where I fetch random questions and options from an API. When users select an option, the next question should appear without reloading the ...

What is the process for running an older Angular project using ng serve?

I'm currently attempting to run a sample Angular project that is part of a third-party framework by using the command ng serve. It seems like this sample project requires Angular version ~4 based on the information in its package.json file. My global ...

The File plugin in Ionic 3 is encountering difficulties in writing files on the device

I am developing an app using Ionic 3 and the file plugin. My goal is to write a JSON string to a JSON file located in my assets folder with the following hierarchy: assets -> mock -> msg-list.json , with "assets" as the main folder in the Ionic files. Wh ...

Error: Angular encountered an issue while loading the resource. Preflight response was not successful

I am attempting to send a request to an API endpoint using Angular in order to retrieve JSON data. Check out my code snippet below: import { Component, OnInit } from '@angular/core'; import {HttpClient} from '@angular/common/http'; imp ...

What is the process for moving data from the store to the form?

When retrieving data from the store, I typically use the following method: ngOnInit(): void { this.store.pipe(select(getPerson)) this.store.dispatch(loadPerson()); } However, I am now faced with the challenge of transferring this data from the ...

The attribute 'positive_rule' is not found within the structure '{ addMore(): void; remove(index: any): void;'

data() { return { positive_rule: [ { positive_rule: "", }, ], }; }, methods: { addMore() { this.positive_rule.push({ positive_rule: "", }); }, ...

Having issues with Angular 2/4 unable to read an object within the initForm() function

In the process of creating an edit form using Angular, I am facing a problem with understanding the lifecycle of the object retrieved from my backend server. After making a call to my service in ngOnInit(), I receive valid data. However, when I assign this ...

What is the best way to keep track of a checkbox's value after unchecking it and then returning to the same slide?

Issue: By default, the checkbox is always set to true in the backend code. Even if I uncheck it using JavaScript, the value remains as true when switching between slides. Desired Outcome: If I uncheck the checkbox, the updated value should be saved so tha ...

What are the recommended guidelines for using TypeScript effectively?

When facing difficulties, I have an array with functions, such as: this._array = [handler, func, type] How should I declare this private property? 1. Array<any> 2. any[] 3. T[] 4. Array<T> What is the difference in these declarations? ...

Resolve the type of the combineLatest outcome in RxJS

Encountering this scenario frequently in Angular when working with combineLatest to merge 2 observables that emit optional values. The basic structure is as follows: const ob1: Observable<Transaction[] | null>; const ob2: Observable<Price[] | nul ...

Using a decorator with an abstract method

Discussing a specific class: export abstract class CanDeactivateComponent { abstract canLeavePage(): boolean; abstract onPageLeave(): void; @someDecorator abstract canDeactivateBeforeUnload(): boolean; } An error occurred stating that A decorat ...

Adjusting image dynamically based on conditions

I need to dynamically display images on my HTML based on specific conditions using TypeScript. In my TypeScript file: styleArray = ["Solitary", "Visual","Auditory","Logical","Physical","Social","Verbal",]; constructor(){ for (var i = 0; this.sty ...

The challenge with the Optional Chaining operator in Typescript 3.7@beta

When attempting to utilize the Typescript optional chaining operator, I encountered the following exception: index.ts:6:1 - error TS2779: The left-hand side of an assignment expression may not be an optional property access. Here is my sample code: const ...

Could it be possible for TypeScript inference to directly infer the value and omit the key in the process?

class A { state: B } class B { something: C } class C { a: string; b: boolean; } type MagicType = ... const c: MagicType<A> c.state.a = "123" c.state.b = true; Is it possible to achieve the mentioned functionality without altering the exi ...