4
votes

I am new to angular2 and working on a basic design to show a list of products and allowing user to add a new item and edit the existing item. For each row there is an edit button which will retrieve the row data and display it on the text areas. For Add and edit i am trying to use the same component. Add option works fine (using ngModel) and it post the data on server without any issues but when i click on edit button the data is not retreived on the modifyoptions.component page. If i click on other rows it starts working properly. If i remove ngModel from modifyoptions.component.html it works fine.

This is my modifyoptions.component.html file.

<label>Price</label>
<input type = "text" id = "itemPrice" value =  {{dataToEdit.price}} [(ngModel)] = "newItemData.price">
<label>Name</label>
<input type = "text" id = "itemName" value =  {{dataToEdit.name}} [(ngModel)] = "newItemData.name">
<label>Brand</label>
<input type = "text" id = "itemBrand" value =  {{dataToEdit.brand}} [(ngModel)] = "newItemData.brand">
<label>Description</label>
<input type = "text" id = "itemDescription" value =  {{dataToEdit.description}} [(ngModel)] = "newItemData.description">

<button type="button" id = "btnSaveItem" (click) = "addNewItems()"
  class="navbar-toggle collapsed" 
  data-toggle="collapse">
    Save</button>

modifyoptions.component.ts

import { Component, OnInit ,Input} from '@angular/core';
import {FetchDataService} from '../Services/fetch-data.service';

@Component({
  selector: 'app-modifyoptions',
  templateUrl: './modifyoptions.component.html',
  styleUrls: ['./modifyoptions.component.css']
})
export class ModifyoptionsComponent implements OnInit {

  constructor(public fetchDataSvc : FetchDataService) { 

  }

  ngOnInit() {
  }

  newItemData:any = {};

  @ Input() dataToEdit:any;


  addNewItems(){
    console.log(this.newItemData);
    this.fetchDataSvc.modifyListOfProducts(this.newItemData)
    .subscribe((result) => {console.log(result)},
    error => {
      console.log(error);
    });
  }
}

My product list file in which i am adding the row and retrieving the value on edit product.component.html

<table class="table table-striped table-hover ">
  <thead>
    <tr>
      <th>#</th>
      <th>id</th>
      <th>Price</th>
      <th>Name</th>
      <th>Brand</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let item of jsonProductList" >
      <td>#</td>
      <td>{{item._id}}</td>
      <td>{{item.price}}</td>
      <td>{{item.name}}</td>
      <td>{{item.brand}}</td>
      <td>{{item.description}}</td>
      <td><button type="button" id = "btnEditItem" (click) =  "showEditDialog(item)"
  class="navbar-toggle collapsed" 
  data-toggle="collapse">
    Edit</button></td>
    </tr>
  </tbody>
</table> 

<div *ngIf="showEditFlag==true">
    <app-modifyoptions [dataToEdit] = "item"></app-modifyoptions>
</div>

Component file :

import { Component, OnInit } from '@angular/core';
import {FetchDataService} from '../Services/fetch-data.service';

@Component({
  selector: 'app-product',
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {

  jsonProductList : any;
  showEditFlag = false;

  item :any;

 // component is already loaded but line 18 will be executed based on the server response.
  constructor(fetchDataSvc : FetchDataService) {
    fetchDataSvc.getListOfProducts().subscribe((result) => {console.log(this.jsonProductList = result)},
    error => {
      console.log(error);
    });
   }

  ngOnInit() {
  }

  showEditDialog(item){
     this.showEditFlag = true;
     this.item = item;
     console.log(item);
  }

}
1
Why do you use 2 different assignments? value = {{dataToEdit.price}} [(ngModel)] = "newItemData.price". Also you're missing quotes on your value. It should be like this: value="{{dataToEdit.price}}" - Aer0
this component is common for both add and edit. with ngModel i am getting the input value from the text area and posting it to the server. with value = {{dataToEdit.price}} i am populating the text areas of the same component when edit is pressed on a row. Double quotes are not required since i am accesing the data from .ts file using {{}} - Ashutosh Bansal

1 Answers

1
votes

It seems it doesn't really like your attempt to use value e.g:

value = {{dataToEdit.price}}

It is actually possible to have two ngModel's. I have no idea if it then breaks your app somehow. You just have to try it :) I found this out by experimenting to use two ngModels in a similar situation, and at least for me it didn't break my app.

So change your value = dataToEdit... to using [(ngModel)]="dataToEdit. ...

EDIT:

Since you in your comment added that you have trouble with separating the new value from editing value. Not knowing how you do create a new item, so this is a bit of a guess....

<div *ngIf="showEditFlag==true">
    <app-modifyoptions [dataToEdit]="item"></app-modifyoptions>
</div>

<div *ngIf="!showEditFlag">
    <app-modifyoptions [dataToEdit]="NewItem></app-modifyoptions>
</div>

I would suggest you actually make two buttons, that you show based on condition and explicitly add the item as parameter in your addNewItems-method. So here you just display or hide the other button, which checks if there is a edited item present, and if so, refer to the ngModel dataToEdit and pass that object in your addNewItem-method. And if it's a new item, you pass the newly created data as a parameter instead.

<button *ngIf="dataToEdit"(click)="addNewItems(dataToEdit)">
    Edit
</button>
<button *ngIf="!dataToEdit" (click)="addNewItems(newItemData)">
    New
</button>

And of course you can then use the same method though for both, since you are passing parameter.

addNewItems(yourObject) {
  console.log(yourObject)
  ....
}