import {
Component,
Input,
ViewChild,
HostListener,
ChangeDetectorRef
} from '@angular/core';
import { AbstractControl } from '@angular/forms';
@Component({
selector: 'sam-fieldset-wrapper',
templateUrl: 'fieldset-wrapper.template.html',
})
export class FieldsetWrapper {
/**
* sets the label text
*/
@Input() public label: string;
/**
* sets the hint text
*/
@Input() public hint: string;
/**
* Add an array of errorMessages
*/
@Input() public errorMessages: any[] = [];
/**
* set a single error message
*/
@Input() public set errorMessage (message: string) {
if (!!message) {
this.errorMessages = [];
this.errorMessages.push(message);
} else {
this.errorMessages = [];
}
};
public get errorMessage (): string {
return this.errorMessages[0];
}
/**
* toggles the required text
*/
@Input() public required: boolean = false;
@ViewChild('hintContainer') public hintContainer: any;
public showToggle: boolean = false;
private toggleOpen: boolean = false;
private lineSize: number;
private lineLimit: number = 2;
private checkMore = false; // semaphore
constructor(private cdr: ChangeDetectorRef) { }
public ngOnChanges(c) {
if (!this.checkMore
&& c.hint
&& c.hint.previousValue !== c.hint.currentValue) {
// needs to be open to recalc correctly in
// ngAfterViewChecked
this.showToggle = false;
this.toggleOpen = false;
this.checkMore = true;
this.cdr.detectChanges();
}
}
public ngAfterViewInit() {
this.calcToggle();
}
public ngAfterViewChecked() {
if (this.checkMore && !this.showToggle) {
this.calcToggle();
this.cdr.detectChanges();
this.checkMore = false;
}
}
public calcToggle() {
if (this.hintContainer) {
const numOfLines =
this.calculateNumberOfLines(
this.hintContainer.nativeElement
);
this.showToggle = numOfLines > this.lineLimit
? true
: false;
}
}
@HostListener('window:resize', ['$event'])
public onResize(event) {
// needs to be open to recalc correctly in
// ngAfterViewChecked
this.showToggle = false;
this.toggleOpen = false;
this.checkMore = true;
this.cdr.detectChanges();
}
public toggleHint(status) {
this.toggleOpen = !status;
}
public calculateNumberOfLines(obj) {
if (!this.lineSize) {
const other = obj.cloneNode(true);
other.innerHTML = 'a
b';
other.style.visibility = 'hidden';
const el = document
.getElementsByTagName('body')[0];
el.appendChild(other);
this.lineSize = other.offsetHeight / 2;
el.removeChild(other);
}
const val = Math.floor(obj.offsetHeight / this.lineSize);
return val;
}
public formatErrors(...controls: AbstractControl[]): void {
this.errorMessages = [];
controls.forEach(
control => this._formatError(control)
);
}
public clearError() {
this.errorMessages = [];
}
public displayErrors (): boolean {
return this.errorMessages.length > 0;
}
public displayErrorList (): boolean {
return this.errorMessages.length > 1;
}
public setOverflow (): string {
return (this.showToggle && !this.toggleOpen)
? 'hidden'
: '' ;
}
public setHeight (): string {
return (this.showToggle && !this.toggleOpen)
? '2.88em'
: ''
}
private _formatError(control: AbstractControl) {
if (!control) {
return;
}
if (control.pristine) {
this.errorMessage = '';
return;
}
if (control.invalid && control.errors) {
this.formatInvalidErrors(control);
} else if (!control.errors) {
this.errorMessage = '';
}
}
private formatInvalidErrors(control) {
for (const k in control.errors) {
const errorObject = control.errors[k];
if (errorObject.message) {
if (Object.prototype.toString.call(errorObject.message)
=== '[object String]') {
this.errorMessages.push(errorObject.message);
return;
}
} else {
this.setInvalidError(k, errorObject);
}
}
}
private setInvalidError(error, errorObject) {
let msg;
switch (error) {
case 'maxlength':
const actualLength = errorObject.actualLength;
const requiredLength = errorObject.requiredLength;
msg = actualLength
+ ' characters input but max length is '
+ requiredLength;
this.errorMessages.push(msg);
return;
case 'required':
msg = 'This field is required';
this.errorMessages.push(msg);
return;
case 'isNotBeforeToday':
msg ='Date must not be before today';
this.errorMessages.push(msg);
return;
default:
msg = 'Invalid'
this.errorMessages.push(msg);
return;
}
}
}