'Why is @Input property standardLinks been overwritten?

I'm currently working on a footer, where I want to display dynamically some links. The standard links should switch accordingly to the property company (which works just fine), but I also want them to change, if they are passed explicitly in the footer.ts file (see property customizedLinks). Apparently the @Input property standardLinks in the links.component.ts file seems to be overwritten, so that the links won't switch when passed explicitly.

Do you have any idea, how to solve this?

Here is my code:

link.component.ts

import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core';
import {Link} from "../models/link.model";

@Component({
  selector: 'app-links',
  template: `
    <div *ngFor="let link of standardLinks">
      <a [href]="link.url">{{ link.name }}</a>
    </div>
  `,
  styleUrls: ['./links.component.css']
})
export class LinksComponent implements OnInit, OnChanges {
  @Input() company: 'a' | 'b' = 'a';
  @Input() standardLinks: Link[] = [];


  ngOnInit(): void {
    this.updateFooterLinks();
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (changes.company) {
      this.updateFooterLinks()
    }
  }

  private updateFooterLinks() {
    if (this.company === 'b') {
      this.standardLinks = [
        new Link('Link 1b', 'blabla.com'),
        new Link('Link 2b', 'blabla.com'),
        new Link('Link 3b', 'blabla.com'),
      ];
    } else {
      this.standardLinks = [
        new Link('Link 1a', 'blabla.com'),
        new Link('Link 2a', 'blabla.com'),
        new Link('Link 3a', 'blabla.com'),
      ]
    }
  }

}

footer.component.html

<div class="row">
  <div class="col">
    <h1>Footer</h1>
  </div>
</div>
<div class="container">
  <div class="row">
  <div class="col">
        <h2>Legal 1</h2>
    </div>
  </div>
  <div class="container">
    <footer>
      <span>Brand 1</span>
      <app-links></app-links>
    </footer>
  </div>
</div>
<div class="container">
  <div class="row">
    <div class="col">
      <h2>Legal 2</h2>
    </div>
  </div>
  <div class="container">
    <footer>
      <span>Brand 2</span>
      <app-links
        [standardLinks]="customizedLinks"
      ></app-links>
    </footer>
  </div>
</div>
<div class="container">
  <div class="row">
    <div class="col">
      <h2>Legal 3</h2>
    </div>
  </div>
  <div class="container">
    <footer>
      <span>Brand 3</span>
      <app-links [company]="'b'"></app-links>
    </footer>
  </div>
</div>

footer.component.ts

import { Component, OnInit } from '@angular/core';
import {Link} from "../models/link.model";

@Component({
  selector: 'app-footer',
  templateUrl: './footer.component.html',
  styleUrls: ['./footer.component.css']
})
export class FooterComponent implements OnInit {
  customizedLinks : Link[] = [
    new Link('bla 1', 'blabla.com'),
    new Link('bla 2', 'blabla.com'),
    new Link('bla 3', 'blabla.com'),
  ]


  ngOnInit(): void {
  }

}

The expected behavior should be:

Footer

Legal 1

Brand 1 Link 1a Link 2a Link 3a

Legal 2

Brand 2 bla 1 bla 2 bla 3

Legal 3

Brand 3 Link 1b Link 2b Link 3b

Note that the code has been simplified.



Solution 1:[1]

Well, I see you're overwritting the value explicitly w/o putting any condition:

enter image description here

In a nutshell, you can solve your problem by adding a condition to your updateFooterLinks function in ngOnInit as follows:

ngOnInit(): void {
  if (!this.standardLinks.length) {
    this.updateFooterLinks();
  }
}

OR

ngOnInit(): void {
  !this.standardLinks.length && this.updateFooterLinks();
}

Bonus: https://stackblitz.com/edit/angular-ivy-1cyz3z

One more thing.. Why you're calling updateFooterLinks in ngOnChanges?

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Abder