ngx-checkbox-list
v2.0.2
Published
Checkbox list form control for Angular X
Downloads
35
Readme
ngx-checkbox-list
Checkbox list form control for Angular X
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Input, Component, forwardRef } from '@angular/core';
import { Option } from './option';
@Component({
selector: 'ngx-checkbox-list',
// eslint-disable-next-line @typescript-eslint/no-use-before-define
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CheckboxListComponent), multi: true }],
template: `
<div [ngClass]="classList">
<div [class]="itemClassName" *ngFor="let o of options; let i = index">
<input
type="checkbox"
[value]="o.value"
[checked]="checked(o.value)"
[attr.id]="name + i"
(change)="change($event)"
/>
<label [attr.for]="name + i">{{ o.label }}</label>
</div>
</div>
`,
})
export class CheckboxListComponent implements ControlValueAccessor {
/**
* Used as prefix to generate unique label/id
*/
@Input() name = '';
/**
* Key/value pairs to produce ui option label and value
*/
@Input() options: Option[];
/**
* Used to format returning value as object of ids
*/
@Input() objectId?: string;
@Input() classList: string[] | string = 'checkbox-list';
/**
* Name of propery for case when need return object with ids
*/
@Input() objectKey?: string;
/**
* Input/label will be wrapped into div with this class name
*/
@Input() itemClassName = '';
private value?: string[];
private onTouched: (_: unknown) => void;
private onChange: (_: unknown) => void;
/**
* Checks if value is selected (checkbox will be mark as checked)
*/
checked(value: unknown): boolean {
if (!this.value) {
return false;
}
return this.value.includes(String(value));
}
/**
* Called when one of checkbox value changed
*/
change(event: Event) {
const input = event.target as HTMLInputElement;
const inputValue = String(input.value);
if (!Array.isArray(this.value)) {
this.value = [];
}
this.value = input.checked ? [...this.value, inputValue] : this.value.filter(v => v !== inputValue);
let formValue: unknown[] = this.value;
if (this.objectId && this.objectKey) {
// If objectId and objectKey are defined, we return {[objectId]: value, [objectKey]: label }[]
const id = this.objectId;
const name = this.objectKey;
// Converts array of values to array of objects.
formValue = this.options
.filter(o => (this.value as string[]).includes(String(o.value)))
.map(o => ({ [id]: o.value, [name]: o.label }));
} else if (this.objectId) {
// If objectId is defined, we return { [id]: o.value }[]
const id = this.objectId;
formValue = this.options
.filter(o => (this.value as string[]).includes(String(o.value)))
.map(o => ({ [id]: o.value }));
} else {
formValue = formValue.filter((value, index, self) => index === self.findIndex(other => other === value));
}
this.onChange(formValue);
}
// Form ControlValueAccessor interface
/**
* Write a new value to the element
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
writeValue(value: any) {
if (!Array.isArray(value)) {
value = value ? [] : null; // eslint-disable-line @typescript-eslint/tslint/config
// eslint-disable-next-line wix-editor/prefer-ternary
} else if (this.objectId) {
value = value.map(v => String(v[this.objectId as string]));
} else {
value = value.map(v => String(v)); // eslint-disable-line @typescript-eslint/tslint/config
}
this.value = value;
}
/**
* Set the function to be called when the control receives a change event
*/
registerOnChange(fn: (_: unknown) => void) {
this.onChange = fn;
}
/**
* Set the function to be called when the control receives a touch event
*/
registerOnTouched(fn: (_: unknown) => void) {
this.onTouched = fn;
}
}