mcpierce
mcpierce

Reputation: 321

Angular4: How do I build a dynamic list of checkboxes to submit in a form?

I'm working on an application where I'm dynamically building a list of items to be submitted to a REST API. My plan is to have the form generate the list of checkbox inputs to let the user select individual elements to be submitted and then, when they hit submit, have only those selected items be sent.

But I can't find an example that comes close to what I'm trying to do.

Here is my component class:

import {Component, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, FormArray, Validators, AbstractControl} from '@angular/forms';

import {File} from '../File';
import {ComicService} from '../comic.service';

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

  directoryForm: FormGroup;
  directory: AbstractControl;
  files: File[];

  constructor(private comicService: ComicService,
    builder: FormBuilder) {
    this.directoryForm = builder.group({'directory': ['', Validators.required]});
    this.directory = this.directoryForm.controls['directory'];
    this.files = [];
    this.selectedFiles = [];
  }

  ngOnInit() {
  }

  onLoad(directory: string): void {
    console.log('Attempt to get a list of comes from:', directory);
    this.comicService.getFilesUnder(directory).subscribe(
      files => {
        this.files = files;
      },
      err => {
        console.log(err);
      }
    );
  }

  toggleSelected(file: File): void {
    file.selected = !file.selected;
  }

  onImportFiles(): void {
    console.log('Attempting to import filenames:', this.selectedFiles);
  }

}

And here is the form:

<div class="ui raised segment">
    <h2 class="ui header">Import Comics</h2>
    <form #f="ngForm" (ngSubmit)="onLoad(directory.value)" class="ui form">
        <div class="field">
            <label for="directory">Root directory:</label> <input type="text"
                id="directory" placeholder="Root Directory"
                [formControl]="directoryForm.controls['directory']">
        </div>

        <button type="submit" class="ui button">Load</button>
    </form>

    <div *ngIf="this.files.length != 0">
        <form (ngSubmit)="onImportFiles(filenames)" class="ui form">
            <table class="ui celled table">
                <thead>
                    <tr>
                        <th></th>
                        <th>Filename</th>
                        <th>Size</th>
                    </tr>
                </thead>
                <tbody>
                    <tr *ngFor="let file of this.files">
                        <!-- How do I get the checkbox to add a filename to be submitted with the form? -->
                        <td><input type="checkbox"></td>
                        <td>{{file.filename}}</td>
                        <td>{{file.size}}</td>
                    </tr>
                </tbody>
            </table>
            <button type="submit" class="ui button">Import</button>
        </form>
    </div>
</div>

Upvotes: 0

Views: 59

Answers (1)

Kelvin Lai
Kelvin Lai

Reputation: 2279

You need to trigger the toggleSelected function when the checkbox is checked/unchecked (changed), and populate the list of selected files by looking at the selected files in files array in your onImportFiles function.

Component:

import {Component, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, FormArray, Validators, AbstractControl} from '@angular/forms';

import {File} from '../File';
import {ComicService} from '../comic.service';

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

  directoryForm: FormGroup;
  directory: AbstractControl;
  files: File[];

  constructor(private comicService: ComicService,
    builder: FormBuilder) {
    this.directoryForm = builder.group({'directory': ['', Validators.required]});
    this.directory = this.directoryForm.controls['directory'];
    this.files = [];
    this.selectedFiles = [];
  }

  ngOnInit() {
  }

  onLoad(directory: string): void {
    console.log('Attempt to get a list of comes from:', directory);
    this.comicService.getFilesUnder(directory).subscribe(
      files => {
        this.files = files;
      },
      err => {
        console.log(err);
      }
    );
  }

  toggleSelected(file: File): void {
    file.selected = !file.selected;
  }

  onImportFiles(): void {
    this.selectedFiles = this.files.filter(file => file.selected).map(file => file.filename);
    console.log('Attempting to import filenames:', this.selectedFiles);
    // TODO: your file importing code here
  }

}

HTML:

<div class="ui raised segment">
    <h2 class="ui header">Import Comics</h2>
    <form #f="ngForm" (ngSubmit)="onLoad(directory.value)" class="ui form">
        <div class="field">
            <label for="directory">Root directory:</label> <input type="text"
                id="directory" placeholder="Root Directory"
                [formControl]="directoryForm.controls['directory']">
        </div>

        <button type="submit" class="ui button">Load</button>
    </form>

    <div *ngIf="this.files.length != 0">
        <form (ngSubmit)="onImportFiles(filenames)" class="ui form">
            <table class="ui celled table">
                <thead>
                    <tr>
                        <th></th>
                        <th>Filename</th>
                        <th>Size</th>
                    </tr>
                </thead>
                <tbody>
                    <tr *ngFor="let file of this.files">
                        <!-- How do I get the checkbox to add a filename to be submitted with the form? -->
                        <td><input type="checkbox" (change)="toggleSelected(file)"></td>
                        <td>{{file.filename}}</td>
                        <td>{{file.size}}</td>
                    </tr>
                </tbody>
            </table>
            <button type="submit" class="ui button">Import</button>
        </form>
    </div>
</div>

Upvotes: 1

Related Questions