0
votes

I have a table whose data is coming from loop.Here when you press add button new similar row will be added at just bottom.Again when you press edit button all textbox will be enable(initially disable).Till now working fine.But when I check single checkbox or multiple checkbox and press delete button all the row based on checked checkbox will be delete/remove.Again when I click delete button without selecting any checkbox alert message should display and also when user selected all check boxes and tried to delete all the row an alert message should be there that 'at least one row should be there' and he cannot delete all rows unless any one row will be unchecked.I am new to angular can anyone please help me.Here is the code below https://stackblitz.com/edit/angular-wscsmy

app.component.html

<div class="container">
    <h2>Basic Table</h2>
    <p>The .table class adds basic styling (light padding and only horizontal dividers) to a table:</p>
    <div><button (click)="enable()">Edit</button> &nbsp;
    <button (click)="delete()">Delete</button> </div>
    <table class="table border">

        <tbody>
            <tr *ngFor="let row of groups;let i = index" (click)="setClickedRow(i)"  [class.active]="i == selectedRow">
              <td> <input type="checkbox"></td>
                <td> <input #focus [disabled]='toggleButton' type="text" value="{{row.name}}"> </td>
                <td> <input [disabled]='toggleButton' type="text" value="{{row.items}}"> </td>
                <td> <button (click)="addRow(i)">Add</button></td>
            </tr>
        </tbody>
    </table>
</div>

app.component.ts

import { Component, ViewChild, ElementRef } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  selectedRow: Number;

  @ViewChild('focus', { static: false }) input: ElementRef;
  public toggleButton: boolean = true;
  ngOnInit() {

  }
  groups = [
    {
      "name": "pencils",
      "items": "red pencil"
    },
    {
      "name": "rubbers",
      "items": "big rubber"
    },
    {
      "name": "rubbers1",
      "items": "big rubber1"
    },
  ];
  addRow(index): void {
    var currentElement = this.groups[index];
    this.groups.splice(index, 0, currentElement);
  }
  enable() {
    this.toggleButton = false
    setTimeout(() => { // this will make the execution after the above boolean has changed
      this.input.nativeElement.focus();
      this.selectedRow = 0;
    }, 0);
  }
  delete(){
    alert('hello');
  }
  setClickedRow(index) {
    this.selectedRow = index;
  }
}
2

2 Answers

0
votes

Use a helper array, where you store all the checked checkboxes. Before deletion, check that at least one value is present.

I choose to store the indexes of the items to the helper array, and based on that, delete from the original array. So perhaps something like this:

toBeDeleted = [];

// called when button is clicked
delete() {
  if (!this.toBeDeleted.length) {
    alert('Choose at least one!');
  } else if (this.toBeDeleted.length === this.groups.length) {
      alert('You cannot delete all rows')
  } 
  else {
    this.groups = this.groups.filter((currentValue, index, arr) => !this.toBeDeleted.includes(index));
  }
  // reset the array
  this.toBeDeleted = [];
}


remove(event, index) {
  // check if checkbox is checked, if so, push to array, else delete from array
  if (event.target.checked) {
    this.toBeDeleted.push(index)
  } else {
    const idx = this.toBeDeleted.indexOf(index);
    this.toBeDeleted.splice(idx, 1)
  }
}

Then in your template, when user clicks on checkbox, call remove() and pass the $event and index of item:

 <td> <input type="checkbox" (click)="remove($event, i)"></td>

STACKBLITZ

0
votes

You have to create an array to keep track of the state of each checkbox. And update it every time a checkbox is checked or unchecked.

Template:

<td>
  <input type="checkbox" (click)="toggleSelection($event, i)" [checked]="checkboxes[i]">
</td>

Component:

checkboxes: boolean[];

ngOnInit() {
   this.checkboxes = new Array(this.groups.length);
   this.checkboxes.fill(false);
}

toggleSelection(event, i) {
  this.checkboxes[i] = event.target.checked;
}

Also, add another checkbox entry to the array whenever a new row is added.

addRow(index): void {
  // Other code.
  this.checkboxes.splice(index, 0, false);
}

You can use Array.splice() to delete elements from an array.

Array.some() can be used to check if at least one checkbox is selected, and Array.every() can be used to check if all the checkboxes are selected.

delete() {
  var atleastOneSelected = this.checkboxes.some(checkbox => checkbox === true);
  var allSelected = this.checkboxes.every(checkbox => checkbox === true);

  if (!atleastOneSelected) {
    alert("No rows selected.");
    return;
  }

  if (allSelected) {
    alert("At least one row should be present.");
    return;
  }

  // Iterating in reverse to avoid index conflicts by in-place deletion.
  for (let i = this.checkboxes.length-1; i >= 0; i--) {
    // If selected, then delete that row.
    if (this.checkboxes[i]) {
      this.groups.splice(i, 1);
    }
  }

  // Remove entries from checkboxes array.
  this.checkboxes = this.checkboxes.filter(checkbox => checkbox === false);
}

Live demo on StackBlitz: https://stackblitz.com/edit/angular-abhkyk