FlashBanistan
FlashBanistan

Reputation: 456

How to achieve 2 way data binding between html table and angular 2 component

I have a table that is populated using the *ngFor directive. A user can click on each cell in the table and edit it's value by virtue of the 'contentEditable' attribute. The current implementation updates the data in the table but doesn't update the data in the component. Is it possible to update the data in the component when the user changes the data in the cell with tools native to angular 2? If so, how?

This is the html file:

<table id="data-table" class="table table-striped">
    <thead>
      <tr>
        <th *ngFor="let round of rounds">{{ round.title }}</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let player of players">
        <td contenteditable="true">{{ player.name }}</td>
        <td contenteditable="true">{{ player.round1 }}</td>
        <td contenteditable="true">{{ player.round2 }}</td>
        <td contenteditable="true">{{ player.round3 }}</td>
      </tr>
    </tbody>
  </table>

This is the component:

import { Component, OnInit } from '@angular/core';
import { BooksAndRunService } from '../books_and_run.service';



@Component({
  moduleId: module.id,
  selector: 'books-and-run-play',
  templateUrl: './books_and_run_play.component.html',
  styleUrls: ['./books_and_run_play.component.css'],
})


export class BooksAndRunPlayComponent implements OnInit {
  constructor(private booksAndRunService: BooksAndRunService) { }
  currentRound = 1;

  rounds = [
    {title: ""},
    {title: "Round 1"},
    {title: "Round 2"},
    {title: "Round 3"},
    {title: "Round 4"},
    {title: "Round 5"},
    {title: "Round 6"},
    {title: "Round 7"},
  ]

  players = [
    {
      name: "Bob",
      round1: 0,
      round2: 0,
      round3: 0,
      round4: 0,
      round5: 0,
      round6: 0,
      round7: 0,
    },
    {
      name: "Joe",
      round1: 0,
      round2: 0,
      round3: 0,
      round4: 0,
      round5: 0,
      round6: 0,
      round7: 0,
    },
    {
      name: "Jim",
      round1: 0,
      round2: 0,
      round3: 0,
      round4: 0,
      round5: 0,
      round6: 0,
      round7: 0,
    },
    {
      name: "Sarah",
      round1: 0,
      round2: 0,
      round3: 0,
      round4: 0,
      round5: 0,
      round6: 0,
      round7: 0,
    },
    {
      name: "Jane",
      round1: 0,
      round2: 0,
      round3: 0,
      round4: 0,
      round5: 0,
      round6: 0,
      round7: 0,
    },
    {
      name: "Jill",
      round1: 0,
      round2: 0,
      round3: 0,
      round4: 0,
      round5: 0,
      round6: 0,
      round7: 0,
    },
  ];



  ngOnInit(): void {
    // this.players = this.booksAndRunService.getPlayers();

  }

}

Upvotes: 2

Views: 4317

Answers (1)

Lys
Lys

Reputation: 568

When using contenteditable="true" you don't get the ngModel attribute, therefore you need to create your own 2 way data binding as such:

<td contenteditable="true" [textContent]="player.name"   (input)="player.name = $event.target.textContent"></td>

Alternatively you can do this

<td contenteditable="true" [textContent]="player.name"   (input)="onContentChanged($event)"></td>

and then in your component class

onContentChanged(event : Event)
    {
        let playerName : string = event.target.textContent;

        .... Do stuff here ....
    }

Upvotes: 2

Related Questions