File

projects/cobbler-frontend/src/app/common/multi-select/multi-select.component.ts

Implements

ControlValueAccessor Validator

Metadata

Index

Properties
Methods
Inputs

Inputs

label
Type : string
Default value : ''

Methods

addOption
addOption()
Returns : void
buildFormGroup
buildFormGroup(options: string[], checked)
Parameters :
Name Type Optional Default value
options string[] No
checked No false
Returns : void
changeValues
changeValues(e: MatCheckboxChange)
Parameters :
Name Type Optional
e MatCheckboxChange No
Returns : void
registerOnChange
registerOnChange(fn: any)
Parameters :
Name Type Optional
fn any No
Returns : void
registerOnTouched
registerOnTouched(fn: any)
Parameters :
Name Type Optional
fn any No
Returns : void
registerOnValidatorChange
registerOnValidatorChange(fn: () => void)
Parameters :
Name Type Optional
fn function No
Returns : void
setDisabledState
setDisabledState(isDisabled: boolean)
Parameters :
Name Type Optional
isDisabled boolean No
Returns : void
updateFormGroup
updateFormGroup(options: string[], checked)
Parameters :
Name Type Optional Default value
options string[] No
checked No false
Returns : void
validate
validate(control: AbstractControl)
Parameters :
Name Type Optional
control AbstractControl No
Returns : ValidationErrors | null
writeValue
writeValue(obj: string[])
Parameters :
Name Type Optional
obj string[] No
Returns : void

Properties

Readonly dialog
Default value : inject(MatDialog)
isDisabled
Default value : true
matSelectOptionsFormGroup
Type : FormGroup<literal type>
Default value : new FormGroup({})
multiSelectOptions
Type : Array<string>
Default value : []
onChange
Type : any
onTouched
Type : any
import { AsyncPipe, NgForOf } from '@angular/common';
import { Component, inject, Input } from '@angular/core';
import {
  AbstractControl,
  ControlValueAccessor,
  FormControl,
  FormGroup,
  NG_VALIDATORS,
  NG_VALUE_ACCESSOR,
  ReactiveFormsModule,
  ValidationErrors,
  Validator,
} from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import {
  MatCheckboxChange,
  MatCheckboxModule,
} from '@angular/material/checkbox';
import { MatDialog } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatListModule } from '@angular/material/list';
import { MatSelectModule } from '@angular/material/select';
import { DialogTextInputComponent } from '../dialog-text-input/dialog-text-input.component';

@Component({
  selector: 'cobbler-multi-select',
  standalone: true,
  imports: [
    MatFormFieldModule,
    MatSelectModule,
    ReactiveFormsModule,
    AsyncPipe,
    MatListModule,
    NgForOf,
    MatCheckboxModule,
    MatButtonModule,
    MatIconModule,
    MatCardModule,
    MatInputModule,
  ],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      multi: true,
      useExisting: MultiSelectComponent,
    },
    {
      provide: NG_VALIDATORS,
      multi: true,
      useExisting: MultiSelectComponent,
    },
  ],
  templateUrl: './multi-select.component.html',
  styleUrl: './multi-select.component.scss',
})
export class MultiSelectComponent implements ControlValueAccessor, Validator {
  multiSelectOptions: Array<string> = [];
  @Input() label = '';
  matSelectOptionsFormGroup: FormGroup<{}> = new FormGroup({});
  onChange: any;
  onTouched: any;
  readonly dialog = inject(MatDialog);
  isDisabled = true;

  buildFormGroup(options: string[], checked = false): void {
    options.forEach((value) => {
      this.matSelectOptionsFormGroup.addControl(
        value,
        new FormControl({ value: checked, disabled: this.isDisabled }),
      );
    });
  }

  updateFormGroup(options: string[], checked = false): void {
    options.forEach((value) => {
      this.matSelectOptionsFormGroup.get(value).setValue(checked);
    });
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    this.isDisabled = isDisabled;
    if (this.isDisabled) {
      this.matSelectOptionsFormGroup.disable();
    } else {
      this.matSelectOptionsFormGroup.enable();
    }
  }

  writeValue(obj: string[]): void {
    this.multiSelectOptions = obj;
    this.buildFormGroup(obj);
    this.updateFormGroup(obj, true);
  }

  registerOnValidatorChange(fn: () => void): void {}

  validate(control: AbstractControl): ValidationErrors | null {
    return undefined;
  }

  changeValues(e: MatCheckboxChange) {
    let options: string[] = [];
    Object.keys(this.matSelectOptionsFormGroup.controls).forEach((key) => {
      const control = this.matSelectOptionsFormGroup.get(key);
      if (control instanceof FormControl) {
        if (control.value) {
          options.push(key);
        }
      }
    });

    this.onTouched(options);
    this.onChange(options);
  }

  addOption(): void {
    const dialogRef = this.dialog.open(DialogTextInputComponent);

    dialogRef.afterClosed().subscribe((result) => {
      if (result === undefined) {
        return;
      }
      const newOptions = Array.from(this.multiSelectOptions);
      newOptions.push(result);
      this.onChange(newOptions);
      this.onTouched();
      this.writeValue(newOptions);
    });
  }
}
<mat-card appearance="outlined">
  <mat-card-header>
    <mat-card-title>{{ label }}</mat-card-title>
  </mat-card-header>
  @if (multiSelectOptions.length === 0) {
    <p style="text-align: center">Empty list of options</p>
  } @else {
    <!-- TODO: See https://github.com/cobbler/cobbler-web/issues/270
    <mat-form-field style="margin: 0 1em">
      <mat-label>Search for option</mat-label>
      <input matInput type="text">
    </mat-form-field>
    -->
    <ng-container [formGroup]="matSelectOptionsFormGroup">
      @for (option of multiSelectOptions; track option) {
        <mat-checkbox
          (change)="changeValues($event)"
          [formControlName]="option"
          [value]="option"
          >{{ option }}</mat-checkbox
        >
      }
    </ng-container>
  }
  <button mat-button [disabled]="isDisabled" (click)="addOption()">
    Add option
  </button>
</mat-card>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""