diff --git a/src/components/input/input.html b/src/components/input/input.html
index 5f0f79086fbf..e76d6f8f15eb 100644
--- a/src/components/input/input.html
+++ b/src/components/input/input.html
@@ -12,11 +12,20 @@
[attr.aria-disabled]="ariaDisabled"
[attr.aria-required]="ariaRequired"
[attr.aria-invalid]="ariaInvalid"
- [id]="inputId"
+ [attr.autocomplete]="autoComplete"
+ [autofocus]="autoFocus"
[disabled]="disabled"
- [required]="required"
- [spellcheck]="spellcheck"
+ [id]="inputId"
+ [attr.list]="list"
+ [attr.max]="max"
[attr.maxlength]="maxLength"
+ [attr.min]="min"
+ [attr.minlength]="minLength"
+ [readonly]="readOnly"
+ [required]="required"
+ [spellcheck]="spellCheck"
+ [attr.step]="step"
+ [attr.tabindex]="tabIndex"
[type]="type"
(focus)="handleFocus($event)"
(blur)="handleBlur($event)"
diff --git a/src/components/input/input.spec.ts b/src/components/input/input.spec.ts
index 11246dd183c9..0b29ba0e72e0 100644
--- a/src/components/input/input.spec.ts
+++ b/src/components/input/input.spec.ts
@@ -283,6 +283,368 @@ export function main() {
})();
});
});
+
+ it('supports the autoComplete attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('autocomplete')).toBeNull();
+
+ fixture.componentInstance.autoComplete = 'on';
+ fixture.detectChanges();
+ expect(el.getAttribute('autocomplete')).toEqual('on');
+ })();
+ });
+ });
+
+ it('supports the autoComplete attribute as an unbound attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('autocomplete')).toEqual('');
+ })();
+ });
+ });
+
+ it('supports the autoComplete attribute as an unbound value attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('autocomplete')).toEqual('name');
+ })();
+ });
+ });
+
+ it('supports the autoFocus attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('autofocus')).toBeNull();
+
+ fixture.componentInstance.autoFocus = true;
+ fixture.detectChanges();
+ expect(el.getAttribute('autofocus')).toEqual('');
+ })();
+ });
+ });
+
+ it('supports the autoFocus attribute as an unbound attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('autofocus')).toEqual('');
+ })();
+ });
+ });
+
+ it('supports the disabled attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.componentInstance.disabled = false;
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('disabled')).toEqual(null);
+
+ fixture.componentInstance.disabled = true;
+ fixture.detectChanges();
+ expect(el.getAttribute('disabled')).toEqual('');
+ })();
+ });
+ });
+
+ it('supports the disabled attribute as an unbound attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('disabled')).toEqual('');
+ })();
+ });
+ });
+
+ it('supports the list attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.componentInstance.disabled = false;
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('list')).toEqual(null);
+
+ fixture.componentInstance.list = 'datalist-id';
+ fixture.detectChanges();
+ expect(el.getAttribute('list')).toEqual('datalist-id');
+ })();
+ });
+ });
+
+ it('supports the max attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.componentInstance.disabled = false;
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('max')).toEqual(null);
+
+ fixture.componentInstance.max = 10;
+ fixture.detectChanges();
+ expect(el.getAttribute('max')).toEqual('10');
+
+ fixture.componentInstance.max = '2000-01-02';
+ fixture.detectChanges();
+ expect(el.getAttribute('max')).toEqual('2000-01-02');
+ })();
+ });
+ });
+
+ it('supports the min attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.componentInstance.disabled = false;
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('min')).toEqual(null);
+
+ fixture.componentInstance.min = 10;
+ fixture.detectChanges();
+ expect(el.getAttribute('min')).toEqual('10');
+
+ fixture.componentInstance.min = '2000-01-02';
+ fixture.detectChanges();
+ expect(el.getAttribute('min')).toEqual('2000-01-02');
+ })();
+ });
+ });
+
+ it('supports the readOnly attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('readonly')).toBeNull();
+
+ fixture.componentInstance.readOnly = true;
+ fixture.detectChanges();
+ expect(el.getAttribute('readonly')).toEqual('');
+ })();
+ });
+ });
+
+ it('supports the readOnly attribute as an unbound attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('readonly')).toEqual('');
+ })();
+ });
+ });
+
+ it('supports the required attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('required')).toBeNull();
+
+ fixture.componentInstance.required = true;
+ fixture.detectChanges();
+ expect(el.getAttribute('required')).toEqual('');
+ })();
+ });
+ });
+
+ it('supports the required attribute as an unbound attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('required')).toEqual('');
+ })();
+ });
+ });
+
+ it('supports the spellCheck attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('spellcheck')).toEqual('false');
+
+ fixture.componentInstance.spellCheck = true;
+ fixture.detectChanges();
+ expect(el.getAttribute('spellcheck')).toEqual('true');
+ })();
+ });
+ });
+
+ it('supports the spellCheck attribute as an unbound attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('spellcheck')).toEqual('true');
+ })();
+ });
+ });
+
+ it('supports the step attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('step')).toEqual(null);
+
+ fixture.componentInstance.step = 0.5;
+ fixture.detectChanges();
+ expect(el.getAttribute('step')).toEqual('0.5');
+ })();
+ });
+ });
+
+ it('supports the tabIndex attribute', () => {
+ var template = '';
+
+ return builder.overrideTemplate(MdInputOptionalAttributeController, template)
+ .createAsync(MdInputOptionalAttributeController)
+ .then(fixture => {
+ fakeAsync(() => {
+ fixture.detectChanges();
+
+ let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
+
+ expect(el).not.toBeNull();
+ expect(el.getAttribute('tabindex')).toEqual(null);
+
+ fixture.componentInstance.tabIndex = 1;
+ fixture.detectChanges();
+ expect(el.getAttribute('tabindex')).toEqual('1');
+ })();
+ });
+ });
});
}
@@ -443,3 +805,12 @@ class MdInputWithBlurAndFocusEvents {
onBlur(event: FocusEvent) {}
onFocus(event: FocusEvent) {}
}
+
+@Component({
+ selector: 'test-input-controller',
+ template: `
+
+ `,
+ directives: [MdInput]
+})
+class MdInputOptionalAttributeController {}
diff --git a/src/components/input/input.ts b/src/components/input/input.ts
index 33de725e0b65..0b92e5570bb4 100644
--- a/src/components/input/input.ts
+++ b/src/components/input/input.ts
@@ -135,14 +135,24 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
*/
@Input() align: 'start' | 'end' = 'start';
@Input() dividerColor: 'primary' | 'accent' | 'warn' = 'primary';
- @Input() @BooleanFieldValue() disabled: boolean = false;
@Input() @BooleanFieldValue() floatingPlaceholder: boolean = true;
@Input() hintLabel: string = '';
+
+ @Input() autoComplete: string;
+ @Input() @BooleanFieldValue() autoFocus: boolean = false;
+ @Input() @BooleanFieldValue() disabled: boolean = false;
@Input() id: string = `md-input-${nextUniqueId++}`;
- @Input() maxLength: number = null;
+ @Input() list: string;
+ @Input() max: string;
+ @Input() maxLength: number = -1;
+ @Input() min: string;
+ @Input() minLength: number;
@Input() placeholder: string;
+ @Input() @BooleanFieldValue() readOnly: boolean = false;
@Input() @BooleanFieldValue() required: boolean = false;
- @Input() @BooleanFieldValue() spellcheck: boolean = false;
+ @Input() @BooleanFieldValue() spellCheck: boolean = false;
+ @Input() step: number;
+ @Input() tabIndex: number;
@Input() type: string = 'text';
private _blurEmitter: EventEmitter = new EventEmitter();