Home > Software engineering >  Child component doesn't update param @Input when parent component is changing the attribute
Child component doesn't update param @Input when parent component is changing the attribute

Time:12-31

Child component doesn't update param @Input when parent component is changing the attribute.

All similar questions I have came across DO NOT solve the problem.

example: The Parent Variable is not updating in the child Component in Angular

or ... https://pretagteam.com/question/angular-child-component-not-updating-after-change-detection

The first time it is created, the property is shared. But when I make a modification from the [(ngModel)] directive (found in the parent), it does NOT propagate the changes to the child component, and therefore the child component does not receive the updated data. (It stays with the previous ones, the ones provided at the beginning).

This is the parent component:


/**
 * Created by cnoe la bestia on 13/12/2021
 **/

import {Component, OnInit} from '@angular/core';
import {Pedido, Status} from "../shared/“app.model";
import {ActivatedRoute, Router} from "@angular/router";
import {DataService} from "../shared/data.service";
import {ClienteApiRestPedidosService} from "../shared/cliente-api-rest-pedidos.service";


@Component({
  selector: 'createPedidoComponent',
  templateUrl: './createPedido.component.html',
  styleUrls: ['./crearPedido.component.css']
})
export class FatherComponent implements OnInit {

  p : string = "p"
  pedido: Pedido ={
    deliveryAddress: "",
    deliveryCity: "",
    deliveryPerson: "",
    status: Status.Ordered,

  } as Pedido;  

...
}

and this is the html (part):

...
      <fieldset >
        <div >
          <label  for="idSeller">idSeller</label>
          <input type="test" 
                 [(ngModel)]="pedido.idSeller" name="idSeller"  >
        </div>
      </fieldset>

      <fieldset >
        <div >
          <label  for="expectedDeliveryDate">expectedDeliveryDate</label>
          <input type="test" 
                 [(ngModel)]="pedido.expectedDeliveryDate" name="expectedDeliveryDate"  >
        </div>
      </fieldset>

      <br>

      <LineaPedidoComponent [pedido] = "pedido" [cabecera] = "cabecera" [llamada] = "p" > </LineaPedidoComponent>

      <br>
...

The child component ts:


/**
 * Created by cnoe la bestia on 20/12/2021
 **/


import {Component, Input, OnInit} from '@angular/core';
import {LineaPedido, Pedido} from "../shared/“app.model";
import {ClienteApiRestPedidosService} from "../shared/cliente-api-rest-pedidos.service";
import {ActivatedRoute, Router} from "@angular/router";

@Component({
  selector: 'LineaPedidoComponent',
  templateUrl: './LineaPedido.component.html',
  styleUrls: ['./LineaPedido.component.css']
})

export class LineaPedidoComponent implements OnInit {
  @Input() pedido : Pedido
  @Input() cabecera : boolean | undefined
  @Input() llamada :string
  id !: number
  json: string


  constructor(private ClienteApiRestPedidosService: ClienteApiRestPedidosService, private ruta: ActivatedRoute,
              private router: Router) {

  }
...
}

Any ideas?

CodePudding user response:

You might try with setter and getter, or with ngOnChanges - depending on how big the Padido data actually is and how often you expect it to change, and how often other vars passed to child change. For a short look at these options, see:

https://javascript.plainenglish.io/dumb-angular-input-setter-getter-vs-ngonchanges-f30e61937926

https://dev.to/angular/angular-setters-vs-ngonchanges-which-one-is-better-4f2b

https://ultimatecourses.com/blog/detect-input-property-changes-ngonchanges-setters

CodePudding user response:

The solution is to change the detection strategy to onpush in your child

@Component({
  selector: 'LineaPedidoComponent',
  templateUrl: './LineaPedido.component.html',
  styleUrls: ['./LineaPedido.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush

})

CodePudding user response:

Both options that you have given me have worked for me when I have removed from my child component an "overwrite" of the attribute that we were linking. This overwriting is done by recovering an order (the tribute that we also ask for) through http.

The reason I have 2 ways to retrieve an order (http and @Input) is as follows:

The child component I call it from different parts, and depending on the part I call it one way or another.

This may be a bad practice, but it was a way to fix that problem quickly.

If I override the attribute when creating the child component, the binding is no longer done correctly (even if you keep modifying the attribute in the parent component).

Removing that part and leaving only for when the attribute we need from the @Input solves this problem. But we must also add the code of @souhail-harrati :)

Thank you very much, it works, although I do not know why when redefining the attribute (and continuing to make modifications in the parent component) it stops binding.

  • Related