Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

414
Vistas
El valor de entrada angular no cambia

Tengo un problema. En mi proyecto Angular tengo 2 componentes con un parámetro de límite bidireccional. El parámetro es un ID de objeto. Ambos componentes usan el mismo servicio que almacena la lista con objetos. El padre contiene la lista donde puede seleccionar el objeto y el hijo muestra los detalles del objeto seleccionado. Aquí está el código del padre:

 <div> <table> <tr> <th scope="col">Title</th> </tr> <tr *ngFor="let offer of service1.findAll();" [style.background-color]="offer.rowClicked ? '#ed9b82' : ''" (click)="highlightClickedRow(offer)"> <td>{{offer.title}}</td> </tr> </table> </div> <div> <app-detail3 [editedOfferId]="offerSelectedId" (editedOfferChanged)="offerSelectedId=$event"></app-detail3> </div>

con el mecanografiado:

 @Component({ selector: 'app-overview3', templateUrl: './overview3.component.html', styleUrls: ['./overview3.component.css'] }) export class Overview3Component implements OnInit { public offerSelectedId: number = -1; constructor(public service1: OffersService) { } ngOnInit(): void { } public highlightClickedRow(offer :Offer) { let offers: Offer[] = this.service1.findAll(); for (let i = 0; i < offers.length; i++) { if (offers[i] != offer) { offers[i].rowClicked = false; } else { offers[i].rowClicked = true; this.offerSelectedId = offers[i].id; } } } }

Y aquí está el componente de detalle:

 <div id="content" *ngIf="editedOfferId != -1"> <div id="data-table"> <table> <tr> <th scope="row" colspan="2">Selected offer details(id = {{service.findById(editedOfferId)!.id}})</th> </tr> <tr> <th scope="row">Title:</th> <td><input type="text" id="txtTitle" (input)="checkObjectChanged()"></td> </tr> <tr> <th scope="row">Description:</th> <td><input type="text" id="txtDescription" (input)="checkObjectChanged()" value="{{service.findById(editedOfferId)!.description}}"></td> </tr> <tr> <th scope="row">Status:</th> <td> <select (input)="checkObjectChanged()" id="txtStatus"> <option *ngFor="let key of keys" [ngValue]="key" [value]="status[key]" [label]="status[key]" [selected]="service.findById(editedOfferId)!.auctionStatus === key"></option> </select> </td> </tr> <tr> <th scope="row">Highest Bid:</th> <td><input id="txtHighestBid" (input)="checkObjectChanged()" value="{{service.findById(editedOfferId)!.valueHighestBid}}"></td> </tr> </table> </div> </div> <div *ngIf="editedOfferId == -1"> <label id="lblNothingSelected">Nothing has been selected yet</label> </div>

Con el mecanografiado:

 @Component({ selector: 'app-detail3', templateUrl: './detail3.component.html', styleUrls: ['./detail3.component.css'] }) export class Detail3Component implements OnInit { @Input() editedOfferId: number = -1; @Output() editedOfferChanged = new EventEmitter<number>(); public selectedOffer: Offer = new Offer("", "", new Date(), AuctionStatus.NEW, 0); status = AuctionStatus keys: Array<number>; constructor(public service: OffersService) { this.keys = Object.keys(this.status).filter(k => !isNaN(Number(k))).map(Number); this.selectedOffer = service.findById(this.editedOfferId)!; } ngOnInit(): void { } }

Ahora, cuando hago clic en un objeto en el componente principal, los detalles se cargarán en el componente de detalle, pero cuando edito, por ejemplo, el campo de entrada del título y luego cambio el objeto en el componente principal, esperaría que los datos del nuevo se cargará el objeto seleccionado. Esto sucede, pero solo los campos que no fueron editados en ese momento, por lo que cuando edite el título, todo se cargará correctamente, pero el valor del título seguirá siendo el mismo. Incluso aunque el objeto tenga un título diferente, el valor que estaba escribiendo permanece en el campo de entrada. ¿Por qué sucede esto y cómo puedo solucionarlo?

over 4 years ago · Santiago Trujillo
4 Respuestas
Responde la pregunta

0

En lugar de usar offerSelectedId en su Overview3Component , cambie su variable para almacenar la referencia completa del objeto.

Entonces, en lugar de public offerSelectedId: number = -1; , usa algo como public offerSelected: Offer = new Offer(...)

A continuación, establezca el elemento seleccionado ( this.offerSelected = offers[i]; ) y pase la referencia ( offerSelected ) a su componente secundario Detail3Component .

 @Component({ selector: 'app-overview3', templateUrl: './overview3.component.html', styleUrls: ['./overview3.component.css'] }) export class Overview3Component implements OnInit { public offerSelected: Offer = new Offer("", "", new Date(), AuctionStatus.NEW, 0); allOffers: Offer[] = []; constructor(public service1: OffersService) { } ngOnInit(): void { this.allOffers = this.service1.findAll(); } public highlightClickedRow(offer :Offer) { for (let i = 0; i < this.allOffers.length; i++) { if (offers[i] != offer) { offers[i].rowClicked = false; } else { offers[i].rowClicked = true; this.offerSelected = offers[i]; // set with entire object } } } }

Recuerde realizar los cambios necesarios en el componente secundario también, cambiando solo el ID de objeto @Input() editedOfferId: number = -1; al objeto @Input() selectedOffer: Offer; .

 @Component({ selector: 'app-detail3', templateUrl: './detail3.component.html', styleUrls: ['./detail3.component.css'] }) export class Detail3Component implements OnInit { // NOTE: This object would be binded back to the source @Input() selectedOffer: Offer = new Offer("", "", new Date(), AuctionStatus.NEW, 0); constructor() { } ngOnInit(): void { } }

Pasar toda la referencia del objeto de esta manera le permitirá cambiar los valores y hacer que se reflejen en el padre, en este caso, la matriz allOffers .

No debería haber necesidad de EventEmitter @Output() editedOfferChanged = new EventEmitter<number>(); a menos que quieras saber si cambiaron algo.

Solo tenga en cuenta que esto solo actualizará los datos en el estado actual y no se guardará en la actualización a menos que implemente alguna lógica de guardado. Además, esta no es de ninguna manera la mejor solución, pero es una solución.

over 4 years ago · Santiago Trujillo Denunciar

0

No ha implementado la lógica de guardar cambios en el componente detail3 y los valores no están vinculados a ningún objeto o variable. Se puede hacer de múltiples maneras. Debe pasar un objeto de oferta al componente secundario en lugar de una identificación para que no tenga que encontrar la oferta seleccionada de todas las ofertas. Vincule el objeto de oferta seleccionado a sus formularios usando ngModel o use formularios reactivos.

Dado que los datos pasados al componente secundario son objetos y cualquier cambio en el objeto se reflejará en la matriz principal (puede evitarlo utilizando el operador de distribución al pasar el valor al componente secundario si no desea que estos cambios se reflejen en la matriz principal y se disparen). un evento para guardar manualmente los datos sobre el cambio).

Preferiría formularios reactivos y el botón enviar/guardar para guardar el cambio. He implementado un ejemplo en stackblitz .

over 4 years ago · Santiago Trujillo Denunciar

0

"el valor del título seguirá siendo el mismo"

 <tr> <th scope="row">Title:</th> <td><input type="text" id="txtTitle" (input)="checkObjectChanged()"></td> </tr>

Su componente secundario no asigna valor para el título.

 value="{{service.findById(editedOfferId)!.title}}"

Parece que el componente principal no vuelve a cargar las ofertas de la lista después de que el componente secundario ya lo actualizó.

Te sugiero que cambies la función:

 (editedOfferChanged)="offerSelectedId=$event"

Para

 (editedOfferChanged)="onEditedOffer($event)"

Para depurar fácilmente y realizar pocas tareas en el componente principal después de que la oferta se actualice en el componente secundario.

Por ejemplo

 onEditedOffer(event){ console.log('onEditedOffer',event; offerSelectedId = event; //do something to update list or single offer. //i choose easy way "reload list offers" offers: Offer[] = this.service1.findAll(); }
over 4 years ago · Santiago Trujillo Denunciar

0

En primer lugar, no implementó la lógica comercial de guardar cambios de su componente de detalles, por lo que, cuando realiza algunos cambios en su objeto, todos los cambios que realizó no se guardarán y luego no se cargarán en su componente principal usando service1. así que recomendamos implementar una solicitud de servicio de guardado de cambios para aplicar los cambios.

para hacer eso exactamente como lo desea con la lógica de su código, use una de esas soluciones:

Solución 1:

Crea un método de actualización para cada campo de oferta en tu OffersService.

 class OffersService { ... updateTitle(offerId:number,newTitle:string){ ... } updateDescription(offerId,newDesc:string){ ... } .... }

En su componente de edición, use el evento onFocuseOut ( el evento de salida de enfoque angular depende de su versión angular ) para cada campo de control, ejemplo para el título:

 <tr> <th scope="row">Title:</th> <td><input type="text" id="txtTitle" (focusout)="service1.updateTitle(editedOfferId,$event.target.value)"></td> </tr>

haga lo mismo para cada uno de los demás campos y asegúrese de actualizarlos. Los métodos también guardan los valores de oferta.

Solución 2:

  • cree un método de servicio en service1 que guarde todos los cambios de un objeto Offer específico. ejemplo:

    class OffersService { ... updateOfferById (id: número, nueva oferta: oferta) { ... } ... }

haga el botón Enviar cambios en su componente de detalles .html, y en su controlador implemente la detección de cambios y llame:

service1.updateOfferById(editedOfferId,changedOffer).subscribe(...);

la diferencia entre los dos métodos, el primero aplica cambios sin usar la acción del usuario para hacer como enviar el botón de cambio, el evento de entrada focusOut hace eso para cada campo en lugar de guardar todos los cambios a la vez.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda