简体   繁体   中英

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.

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 class="form-group">
        <div class="col-sm-3">
          <label class="control-label" for="idSeller">idSeller</label>
          <input type="test" class="form-control"
                 [(ngModel)]="pedido.idSeller" name="idSeller"  >
        </div>
      </fieldset>

      <fieldset class="form-group">
        <div class="col-sm-3">
          <label class="control-label" for="expectedDeliveryDate">expectedDeliveryDate</label>
          <input type="test" class="form-control"
                 [(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?

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

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

})

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM