Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Input value doesn't change

I have a problem. In my Angular project I have 2 components with an two-way bound parameter. The parameter is an object id. Both components use the same service which stores the list with objects. The parent contains the list where you can select the object and the child shows the selected object details. Here is the code of the parent:

<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>

with the typescript:

@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;
      }
    }
  }

}

And here is the detail component:

<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>

With the typescript:

@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 {
  }

}

Now when I click on an object in the parent component, the details will be loaded in de detail component, but when I edit for example the title input field and then change the object in the parent, I would expect that the data of the new selected object will be loaded. This happens, but only the fields that were not edited at that moment, so when I edit the title, everything will be loaded correctly, but the value of the title will remain the same. Even tough the object has a different title, the value that I was typing stays in the input field. Why is this happening and how can I fix this?

like image 618
A. Vreeswijk Avatar asked Aug 22 '26 09:08

A. Vreeswijk


1 Answers

First of all , you did not implement your save changes business logic of your details component , so , when you make some changes in your object , all changes you made will not save then will not be loaded in your parent component using service1. so recommend implementing a save change service request to apply changes .

to do that exactly how you want by your code logic , Use one of those solutions:

Solution 1:

Create an update method for each offer field in your OffersService.

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

In your edit component use onFocuseOut event ( angular focus Out event depend to your angular version ) to each control field , example for title:

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

please do the same thing for each other fields and make sure your update.. methods save offer values as well .

Solution 2:

  • create a service method in service1 that saves all changes of a specific Offer object. example:

    class OffersService { ... updateOfferById(id:number,newOffer:Offer) { ... } ... }

make submit changes button in your details component .html , and in its handler implement change detection and call :

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

the difference between the two methods , the first apply changes without using user action to do like submit change button, the input focusOut event do that for each field instead of saving all changes at once .

like image 187
Med Mahdi Maarouf Avatar answered Aug 24 '26 23:08

Med Mahdi Maarouf



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!