|
| 1 | +import { |
| 2 | + forwardRef, |
| 3 | + Component, |
| 4 | + HostBinding, |
| 5 | + Input, |
| 6 | + Output, |
| 7 | + Provider, |
| 8 | +} from 'angular2/core'; |
| 9 | +import {EventEmitter} from 'angular2/src/facade/async'; |
| 10 | +import {CONST_EXPR, noop} from 'angular2/src/facade/lang'; |
| 11 | +import {MdAriaTarget, MdAria} from '../../core/utilities/aria-directives'; |
| 12 | +import { |
| 13 | + NG_VALUE_ACCESSOR, |
| 14 | + ControlValueAccessor |
| 15 | +} from 'angular2/src/common/forms/directives/control_value_accessor'; |
| 16 | +import {BooleanFieldValue} from '../../core/annotations/field-value'; |
| 17 | +import {OneOf} from '../../core/annotations/one-of'; |
| 18 | + |
| 19 | + |
| 20 | +const MD_INPUT_CONTROL_VALUE_ACCESSOR = CONST_EXPR(new Provider( |
| 21 | + NG_VALUE_ACCESSOR, { |
| 22 | + useExisting: forwardRef(() => MdInput), |
| 23 | + multi: true |
| 24 | + })); |
| 25 | + |
| 26 | + |
| 27 | +let uniqueId = 0; |
| 28 | + |
| 29 | + |
| 30 | +/** |
| 31 | + * <md-input> component. |
| 32 | + */ |
| 33 | +@Component({ |
| 34 | + selector: 'md-input', |
| 35 | + templateUrl: 'components/input/input.html', |
| 36 | + styleUrls: ['components/input/input.css'], |
| 37 | + providers: [MdAria, MD_INPUT_CONTROL_VALUE_ACCESSOR], |
| 38 | + directives: [MdAriaTarget], |
| 39 | +}) |
| 40 | +export class MdInput implements ControlValueAccessor { |
| 41 | + private _empty: boolean = true; |
| 42 | + private _focused: boolean = false; |
| 43 | + private _onTouched: () => void = noop; |
| 44 | + private _onChangeFn: (_: any) => void = noop; |
| 45 | + private _value: any = ''; |
| 46 | + private _inputId: number = uniqueId++; |
| 47 | + |
| 48 | + get focused() { return this._focused; } |
| 49 | + get empty() { return this._empty; } |
| 50 | + |
| 51 | + @Input() @BooleanFieldValue() characterCounter: boolean = false; |
| 52 | + @Input() @BooleanFieldValue() disabled: boolean = false; |
| 53 | + @Input() @BooleanFieldValue() required: boolean = false; |
| 54 | + @Input() @BooleanFieldValue() floatingPlaceholder: boolean = true; |
| 55 | + |
| 56 | + @Input() @OneOf(['primary', 'accent']) dividerColor: string = 'primary'; |
| 57 | + @Input() @OneOf(['start', 'end']) align: string = 'start'; |
| 58 | + @Input() hintLabel: string = ''; |
| 59 | + @Input() maxLength: number = -1; |
| 60 | + @Input() placeholder: string; |
| 61 | + @Input() type: string = 'text'; |
| 62 | + |
| 63 | + get value(): any { return this._value; }; |
| 64 | + @Input() set value(v: any) { |
| 65 | + if (this._value !== v) { |
| 66 | + this._value = v; |
| 67 | + this._empty = v === undefined || v === null || (''+v == ''); |
| 68 | + this._onChangeFn(v); |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + @Output('change') change = new EventEmitter(false); |
| 73 | + |
| 74 | + @HostBinding('attr.align') private get _align(): any { return null; } |
| 75 | + |
| 76 | + /** @override */ |
| 77 | + writeValue(value: any) { |
| 78 | + if (this._value !== value) { |
| 79 | + this._value = value; |
| 80 | + this._empty = value === undefined || value === null || (''+value == ''); |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + /** @override */ |
| 85 | + registerOnChange(fn: any) { |
| 86 | + this._onChangeFn = fn; |
| 87 | + } |
| 88 | + |
| 89 | + /** @override */ |
| 90 | + registerOnTouched(fn: any) { |
| 91 | + this._onTouched = fn; |
| 92 | + } |
| 93 | + |
| 94 | + onFocus() { |
| 95 | + this._focused = true; |
| 96 | + } |
| 97 | + onBlur() { |
| 98 | + this._focused = false; |
| 99 | + this._onTouched(); |
| 100 | + } |
| 101 | + |
| 102 | + private _characterCounterLabel(): string { |
| 103 | + if (this.characterCounter) { |
| 104 | + return String(this.value || '').length + (this.maxLength > 0 ? ' / ' + this.maxLength : ''); |
| 105 | + } else { |
| 106 | + return ''; |
| 107 | + } |
| 108 | + } |
| 109 | +} |
| 110 | + |
| 111 | +export const MD_INPUT_DIRECTIVES: any[] = CONST_EXPR([ |
| 112 | + MdInput, |
| 113 | + MdAria, |
| 114 | +]); |
0 commit comments