3

I have an ngFor loop displaying several list items. Each list item contains a title. It also contains an input with the title inside it which I want hidden. When I hit an edit button, I want the input for that selected item to show, none of the others. What's the best way to approach this?

Below is what I have so far. However, when initiating 'editItem' and setting 'editable' to true, the input box for all items appears, not just the one I clicked on.

editable = false;

editItem(){
  this.editable = true;
}
<ul>
  <li *ngFor="let item of items | async">
    <div class="item">
      <div class="title"> {{ item.item_title }}</div>
      <input #newItemName type="text" [(ngModel)]="this.item.item_title" *ngIf="editable"/>
      <i aria-hidden="true" (click)="editItem()"></i>
     </div>
  </li>
</ul>

Any assistance would be greatly appreciated :)

coturiv
  • 2,880
  • 22
  • 39
MegaTron
  • 3,133
  • 6
  • 28
  • 45
  • 1
    this would be a good place to abstract out the list items into a separate component. if you do that then your code will work. – JoshSommer Dec 21 '17 at 18:56
  • Best way would be retrieve the list of items in your TS. Add `editable` field to each item on the client side `items.forEach(item => item['editable'] = false)` then `*ngIf="item.editable"` – Chau Tran Dec 21 '17 at 18:56
  • It's simple but provide a UI example! input/s and edit button/s. How are these working? Edit button appears appears only for the selected element? How is the element selected? – Marian07 Dec 21 '17 at 19:19

2 Answers2

4

You can fix it easily ^^

typescript

editItem(item: any){
  item.editable = true;
}

html

<ul>
  <li *ngFor="let item of items | async">
    <div class="item">
      <div class="title"> {{ item.item_title }}</div>
      <input #newItemName type="text" [(ngModel)]="this.item.item_title" *ngIf="item.editable"/>
      <i aria-hidden="true" (click)="editItem(item)"></i>
     </div>
  </li>
</ul>
Colper
  • 115
  • 2
  • 8
coturiv
  • 2,880
  • 22
  • 39
  • What an elegant solution. Thank you. I'll this as the answer the moment I'm able to. As a quick follow up: this solution shows the input for the selected item, if I then select another item, is it possible to hide all others (that have already been opened?) – MegaTron Dec 21 '17 at 19:21
1

You can.. create an editMode boolean, and array of editStates booleans (one for each item) in component.ts

editMode = false;
editable = new Array<boolean>(this.items.length);

Then convert function to set all to false, and edit

  • on click event: editItem, feed it the index (so in your ngFor loop add let i = index) item, and set use quick false fill array followed by index of choice to true.

  • on hoverout exit event: exitEditMode.


  editItem(index: number) {
    this.editMode = true;
    this.editable.fill(false);
    this.editable[index] = true;
  }

  exitEditMode() {
    this.editMode = false;
  }

Then in the html, you can use ngIf to hide all editables that are disabled in edit mode, by probing for editMode and editable selected. Something like this:

<ul>
  <li *ngFor="let item of items | async; let i = index">
    <div class="item">
      <div class="title"> {{ item.item_title }}</div>
      <input #newItemName type="text" [(ngModel)]="this.item.item_title" *ngIf="editable"/>
      <i aria-hidden="true" *ngIf="editMode && editable[i]" (click)="editItem(i)" (mouseout)="exitEditMode()"></i>
    </div>
  </li>
</ul>
Iancovici
  • 5,574
  • 7
  • 39
  • 57