108 lines
3.1 KiB
TypeScript
108 lines
3.1 KiB
TypeScript
![]() |
import {
|
||
|
AfterViewInit,
|
||
|
Component,
|
||
|
ContentChild,
|
||
|
Directive,
|
||
|
forwardRef,
|
||
|
HostListener,
|
||
|
Input,
|
||
|
OnInit,
|
||
|
TemplateRef
|
||
|
} from '@angular/core';
|
||
|
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
|
||
|
import _ from 'lodash';
|
||
|
import {ArrayInputHelperService} from './array-input-helper.service';
|
||
|
|
||
|
// TODO: implement everywhere
|
||
|
|
||
|
@Directive({ // directive for template and input values
|
||
|
// tslint:disable-next-line:directive-selector
|
||
|
selector: '[rbArrayInputItem]'
|
||
|
})
|
||
|
export class RbArrayInputItemDirective {
|
||
|
constructor(public templateRef: TemplateRef<any>) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Directive({ // directive for change detection
|
||
|
// tslint:disable-next-line:directive-selector
|
||
|
selector: '[rbArrayInputListener]'
|
||
|
})
|
||
|
export class RbArrayInputListenerDirective {
|
||
|
|
||
|
@Input() rbArrayInputListener: string;
|
||
|
@Input() index: number;
|
||
|
|
||
|
constructor(
|
||
|
private helperService: ArrayInputHelperService
|
||
|
) { }
|
||
|
|
||
|
@HostListener('ngModelChange', ['$event'])
|
||
|
onChange(event) {
|
||
|
console.log(event);
|
||
|
this.helperService.newValue(this.rbArrayInputListener, this.index, event);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
@Component({
|
||
|
// tslint:disable-next-line:component-selector
|
||
|
selector: 'rb-array-input',
|
||
|
templateUrl: './rb-array-input.component.html',
|
||
|
styleUrls: ['./rb-array-input.component.scss'],
|
||
|
providers: [{provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RbArrayInputComponent), multi: true}]
|
||
|
})
|
||
|
export class RbArrayInputComponent implements ControlValueAccessor, OnInit, AfterViewInit {
|
||
|
|
||
|
@Input() pushTemplate: any;
|
||
|
@Input() pushPath: string;
|
||
|
|
||
|
@ContentChild(RbArrayInputItemDirective) item: RbArrayInputItemDirective;
|
||
|
@ContentChild(RbArrayInputListenerDirective) item2: RbArrayInputListenerDirective;
|
||
|
|
||
|
values = []; // main array to display
|
||
|
|
||
|
onChange = (ignore?: any): void => {};
|
||
|
onTouched = (ignore?: any): void => {};
|
||
|
|
||
|
|
||
|
constructor(
|
||
|
private helperService: ArrayInputHelperService
|
||
|
) { }
|
||
|
|
||
|
ngOnInit(): void {
|
||
|
}
|
||
|
|
||
|
ngAfterViewInit() {
|
||
|
setTimeout(() => { // needed to find reference
|
||
|
this.helperService.values(this.item2.rbArrayInputListener).subscribe(data => { // action on value change
|
||
|
this.values[data.index][this.pushPath] = data.value;
|
||
|
console.log(this.values);
|
||
|
if (this.values[this.values.length - 1][this.pushPath] === '' && this.values[this.values.length - 2][this.pushPath] === '') { // remove last element if last two are empty
|
||
|
this.values.pop();
|
||
|
}
|
||
|
else if (this.values[this.values.length - 1][this.pushPath] !== '') { // add element if last one is filled
|
||
|
this.values.push(_.cloneDeep(this.pushTemplate));
|
||
|
}
|
||
|
this.onChange(this.values.filter(e => e !== '')); // trigger ngModel with filled elements
|
||
|
});
|
||
|
}, 0);
|
||
|
}
|
||
|
|
||
|
writeValue(obj: any) { // add empty value on init
|
||
|
this.values = obj ? obj : [];
|
||
|
if (this.values.length === 0 || this.values[0] !== '') {
|
||
|
console.log(this.values);
|
||
|
this.values.push(_.cloneDeep(this.pushTemplate));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
registerOnChange(fn: any) {
|
||
|
this.onChange = fn;
|
||
|
}
|
||
|
|
||
|
registerOnTouched(fn: any) {
|
||
|
this.onTouched = fn;
|
||
|
}
|
||
|
}
|