All files / src/components/zd-number-input number-input.ts

100% Statements 58/58
100% Branches 33/33
100% Functions 9/9
100% Lines 56/56

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 15093x 93x 93x 93x           93x           42x         42x                     42x   42x   42x                                 54x 53x 53x       141x       164x 163x 163x 20x 20x 2x     143x 143x 1x                 6x       5x 2x 2x 2x 1x     3x 3x   2x 2x 1x 1x 1x   1x                   6x                 6x       93x 6x   6x 1x 1x   6x 6x 6x     93x 6x   6x 1x 1x   6x 6x 6x     93x  
import { Accessor, Config, FormatterParserProvider, Loader } from '@zeedhi/core';
import { AutoNumeric } from '../../index';
import { InputFactory } from '../zd-input/input-factory';
import { TextInput } from '../zd-text-input/text-input';
import { INumberInput } from './interfaces';
 
/**
 * Base class for Number component
 */
export class NumberInput extends TextInput implements INumberInput {
	/*
	 * Mask definition
	 */
	public mask: any;
 
	protected defaultMask: any = Config.masks.numberMask || {};
 
	/*
	 * Defines how the field content should be aligned.
	 */
	public align = 'right';
 
	/**
	 * AutoNumeric object
	 */
	public autoNumericObj: any;
 
	private formattedValue?: string;
 
	private localValue?: number;
 
	protected formatterFn = FormatterParserProvider.getFormatter('ZdNumberInput');
 
	protected parserFn = FormatterParserProvider.getParser('ZdNumberInput');
 
	private maskValid = false;
 
	/* istanbul ignore next */
	/**
	 * Creates a new number input
	 */
	constructor(props: INumberInput) {
		super(props);
		const newMask = { ...this.defaultMask, ...props.mask };
		this.align = this.getInitValue('align', props.align, this.align);
		this.mask = this.getInitValue('mask', newMask, this.defaultMask);
		this.value = this.getInitValue('value', props.value, this.value);
		this.createAccessors();
		this.validateMask();
	}
 
	public validateMask() {
		AutoNumeric.validate(this.mask, true);
		this.maskValid = true;
		this.value = this.localValue; // force atualization after validate mask
	}
 
	get value(): any {
		return this.localValue;
	}
 
	set value(value: any) {
		if (typeof value === 'string' && window.Number.isNaN(parseFloat(value))) return;
		this.localValue = value;
		if (this.maskValid && this.localValue !== undefined && this.localValue !== null) {
			this.formattedValue = AutoNumeric.format(this.localValue, this.mask);
			if (this.autoNumericObj && value !== this.autoNumericObj.rawValue) {
				this.autoNumericObj.setValue(value);
			}
		} else {
			this.formattedValue = '';
			if (this.autoNumericObj) {
				this.autoNumericObj.clear();
			}
		}
	}
 
	/**
	 * Input displayed value.
	 */
	get displayValue(): any {
		return this.formattedValue;
	}
 
	set displayValue(value: any) {
		if (!value) {
			this.formattedValue = '';
			this.localValue = undefined;
			if (this.autoNumericObj) {
				this.autoNumericObj.clear();
			}
		} else {
			this.formattedValue = value;
			if (!this.autoNumericObj) return;
 
			const parsed = parseFloat(this.autoNumericObj.rawValue);
			if (window.Number.isNaN(parsed)) {
				this.localValue = undefined;
				this.autoNumericObj.clear();
				return;
			}
			this.localValue = parsed;
		}
	}
 
	/**
	 * Retrieves a formatted value with mask
	 * @param value Any value
	 * @returns A Formatted value
	 */
	public formatter(value: any): string {
		return this.formatterFn(value, this);
	}
 
	/**
	 * Retrieves a parsed value without mask
	 * @param value Any value
	 * @returns A parsed value
	 */
	public parser(value: any): any {
		return this.parserFn(value, this);
	}
}
 
FormatterParserProvider.registerFormatter('ZdNumberInput', (value: any, { mask = {} }: any = {}) => {
	let maskDef = mask;
 
	if (Accessor.isAccessorDefinition(maskDef)) {
		const [controller, accessor] = Accessor.getAccessor(maskDef);
		maskDef = Loader.getInstance(controller)[accessor];
	}
	let maskValue = typeof maskDef === 'function' ? maskDef(AutoNumeric.unformat(value)) : maskDef;
	maskValue = { ...Config.masks.numberMask, ...maskValue };
	return value === null ? '' : AutoNumeric.format(value, maskValue);
});
 
FormatterParserProvider.registerParser('ZdNumberInput', (value: any, { mask = {} }: any = {}) => {
	let maskDef = mask;
 
	if (Accessor.isAccessorDefinition(maskDef)) {
		const [controller, accessor] = Accessor.getAccessor(maskDef);
		maskDef = Loader.getInstance(controller)[accessor];
	}
	let maskValue = typeof maskDef === 'function' ? maskDef(AutoNumeric.format(value)) : maskDef;
	maskValue = { ...Config.masks.numberMask, ...maskValue };
	return value === '' ? null : AutoNumeric.unformat(value, maskValue);
});
 
InputFactory.register('ZdNumberInput', NumberInput);