|  | 
| 1 |  | -import {Directive} from 'angular2/src/core/annotations_impl/annotations'; | 
|  | 1 | +import {Directive, onAllChangesDone} from 'angular2/src/core/annotations_impl/annotations'; | 
|  | 2 | +import {Attribute} from 'angular2/src/core/annotations_impl/di'; | 
|  | 3 | +import {Parent} from 'angular2/src/core/annotations_impl/visibility'; | 
|  | 4 | + | 
|  | 5 | +import {ObservableWrapper, EventEmitter} from 'angular2/src/facade/async'; | 
|  | 6 | + | 
|  | 7 | +// TODO(jelbourn): validation (will depend on Forms API). | 
|  | 8 | +// TODO(jelbourn): textarea resizing | 
|  | 9 | +// TODO(jelbourn): max-length counter | 
|  | 10 | +// TODO(jelbourn): placeholder property | 
| 2 | 11 | 
 | 
| 3 | 12 | @Directive({ | 
| 4 |  | -  selector: 'md-input-container input' | 
|  | 13 | +  selector: 'md-input-container input', | 
|  | 14 | +  events: ['mdChange', 'mdFocusChange'], | 
|  | 15 | +  hostProperties: { | 
|  | 16 | +    'yes': 'class.md-input' | 
|  | 17 | +  }, | 
|  | 18 | +  hostListeners: { | 
|  | 19 | +    'input': 'updateValue($event)', | 
|  | 20 | +    'focus': 'setHasFocus(true)', | 
|  | 21 | +    'blur': 'setHasFocus(false)' | 
|  | 22 | +  } | 
| 5 | 23 | }) | 
| 6 | 24 | export class MdInput { | 
| 7 |  | -  constructor() { | 
|  | 25 | +  value: string; | 
|  | 26 | +  yes: boolean; | 
| 8 | 27 | 
 | 
|  | 28 | +  // Events emitted by this directive. We use these special 'md-' events to communicate | 
|  | 29 | +  // to the parent MdInputContainer. | 
|  | 30 | +  mdChange: EventEmitter; | 
|  | 31 | +  mdFocusChange: EventEmitter; | 
|  | 32 | + | 
|  | 33 | +  constructor( | 
|  | 34 | +      @Attribute('value') value: String, | 
|  | 35 | +      @Parent() container: MdInputContainer) { | 
|  | 36 | +    // TODO(jelbourn): Remove this when #1402 is done. | 
|  | 37 | +    this.yes = true; | 
|  | 38 | + | 
|  | 39 | +    this.value = value == null ? '' : value; | 
|  | 40 | +    this.mdChange = new EventEmitter(); | 
|  | 41 | +    this.mdFocusChange = new EventEmitter(); | 
|  | 42 | + | 
|  | 43 | +    container.registerInput(this); | 
|  | 44 | +  } | 
|  | 45 | + | 
|  | 46 | +  updateValue(event) { | 
|  | 47 | +    this.value = event.target.value; | 
|  | 48 | +    ObservableWrapper.callNext(this.mdChange, this.value); | 
|  | 49 | +  } | 
|  | 50 | + | 
|  | 51 | +  setHasFocus(hasFocus: boolean) { | 
|  | 52 | +    ObservableWrapper.callNext(this.mdFocusChange, hasFocus); | 
| 9 | 53 |   } | 
| 10 | 54 | } | 
| 11 | 55 | 
 | 
|  | 56 | +@Directive({ | 
|  | 57 | +  selector: 'md-input-container textarea', | 
|  | 58 | +  events: ['mdChange', 'mdFocusChange'], | 
|  | 59 | +  hostProperties: { | 
|  | 60 | +    'yes': 'class.md-input' | 
|  | 61 | +  }, | 
|  | 62 | +  hostListeners: { | 
|  | 63 | +    'input': 'updateValue($event)', | 
|  | 64 | +    'focus': 'setHasFocus(true)', | 
|  | 65 | +    'blur': 'setHasFocus(false)' | 
|  | 66 | +  } | 
|  | 67 | +}) | 
|  | 68 | +export class MdTextarea extends MdInput { | 
|  | 69 | +  constructor( | 
|  | 70 | +      @Attribute('value') value: String, | 
|  | 71 | +      @Parent() container: MdInputContainer) { | 
|  | 72 | +    super(value, container); | 
|  | 73 | +  } | 
|  | 74 | +} | 
| 12 | 75 | 
 | 
| 13 | 76 | @Directive({ | 
| 14 |  | -  selector: 'md-input-container' | 
|  | 77 | +  selector: 'md-input-container', | 
|  | 78 | +  lifecycle: [onAllChangesDone], | 
|  | 79 | +  hostProperties: { | 
|  | 80 | +    'inputHasValue': 'class.md-input-has-value', | 
|  | 81 | +    'inputHasFocus': 'class.md-input-focused' | 
|  | 82 | +  } | 
| 15 | 83 | }) | 
| 16 | 84 | export class MdInputContainer { | 
|  | 85 | +  // The MdInput or MdTextarea inside of this container. | 
|  | 86 | +  _input: MdInput; | 
|  | 87 | + | 
|  | 88 | +  // Whether the input inside of this container has a non-empty value. | 
|  | 89 | +  inputHasValue: boolean; | 
|  | 90 | + | 
|  | 91 | +  // Whether the input inside of this container has focus. | 
|  | 92 | +  inputHasFocus: boolean; | 
|  | 93 | + | 
|  | 94 | +  constructor() { | 
|  | 95 | +    this._input = null; | 
|  | 96 | +    this.inputHasValue = false; | 
|  | 97 | +    this.inputHasFocus = false; | 
|  | 98 | +  } | 
|  | 99 | + | 
|  | 100 | +  onAllChangesDone() { | 
|  | 101 | +    // Enforce that this directive actually contains a text input. | 
|  | 102 | +    if (this._input == null) { | 
|  | 103 | +      throw 'No <input> or <textarea> found inside of <md-input-container>'; | 
|  | 104 | +    } | 
|  | 105 | +  } | 
|  | 106 | + | 
|  | 107 | +  /** Registers the child MdInput or MdTextarea. */ | 
|  | 108 | +  registerInput(input) { | 
|  | 109 | +    if (this._input != null) { | 
|  | 110 | +      throw 'Only one text input is allowed per <md-input-container>.'; | 
|  | 111 | +    } | 
|  | 112 | + | 
|  | 113 | +    this._input = input; | 
|  | 114 | +    this.inputHasValue = input.value != ''; | 
|  | 115 | + | 
|  | 116 | +    // Listen to input changes and focus events so that we can apply the appropriate CSS | 
|  | 117 | +    // classes based on the input state. | 
|  | 118 | +    ObservableWrapper.subscribe(input.mdChange, value => { | 
|  | 119 | +      this.inputHasValue = value != ''; | 
|  | 120 | +    }); | 
|  | 121 | + | 
|  | 122 | +    ObservableWrapper.subscribe(input.mdFocusChange, hasFocus => { | 
|  | 123 | +      this.inputHasFocus = hasFocus | 
|  | 124 | +    }); | 
|  | 125 | +  } | 
| 17 | 126 | } | 
0 commit comments