angulartypescriptangular-lifecycle-hooks

Inject a fetched value from the url in a child component Angular


I'm trying to inject a value from an the Url that I want to inject in a child component. I'm able to get the param from the url and update my DOM with a property but the same property doesn't behave the same way when I inject it in a child component.

Here my parent component:

@Component({
  selector: 'app-posts',
  templateUrl: 
`
<div class="container">
  <h1><app-task-title [taskId]="router"></app-task-title></h1>
  <h2>{{router}}</h2>
  <app-tab [tacheLabelId]="router"></app-tab>
</div>
`,
  styleUrls: ['./posts.component.scss']
})
export class PostsComponent implements OnInit, DoCheck {

  /**Variables from the url */
  router! : number


  constructor(private route : ActivatedRoute) { }


  ngDoCheck(): void {
    this.router = Number(this.route.snapshot.paramMap.get('route'));
  }

  ngOnInit(): void {
  }
}

I can see the h2 tag change but not the others

Here is my child component:

@Component({
  selector: 'app-task-title',
  template: `
      {{taskLabel}}
  `,
  styles: [
  ]
})
export class TaskTitleComponent implements OnInit {

  @Input() taskId! : number;
  taskLabel!: string;
  constructor() { }

  ngOnInit(): void {
    switch (this.taskId) {
      case 1:
        this.taskLabel = "Title 1"
        break;
      case 2:
        this.taskLabel = "Title 2"
        break;
      case 3:
        this.taskLabel = "Title 3"
        break;
      case 4:
        this.taskLabel = "Title 4"
        break;

      default:
        this.taskLabel = "Title 0"
        break;
    }
  }

}

What I already tried:

  1. Use the router property as a string and then used that syntax: <h1><app-task-title taskId={{router}}></app-task-title></h1> but the result is the same.
  2. Use a method that returns the value in the DOM.

If you have any explanation about how behaves the property in the DOM, it is welcome


Solution

  • My guess is that ngOnInit is called too soon in the child component and taskId is not valued yet. If you want to be sure, you can use the @Input on a setter instead :

    export class TaskTitleComponent {
    
      // You might not need this attribute anymore
      private _taskId! : number;
      taskLabel!: string;
    
      @Input()
      set taskId(taskId: number) {
        this._taskId = taskId;
        switch (this._taskId) {
          case 1:
            this.taskLabel = "Title 1"
            break;
          [...]
      }