From 2055653bba31c490f724ffe9c0bbfd773b1dc5f8 Mon Sep 17 00:00:00 2001
From: Paul Gschwendtner
Date: Tue, 10 Jan 2017 14:08:02 +0100
Subject: [PATCH 1/4] feat(input): option to imperatively float placeholder
Refactors the `[floatingPlaceholder]` input to be able to specifiy whether the label should always float or not.
There are three options for the `floatingPlaceholder` input binding now
- If set to `true`, the placeholder will *always* float
- If set to `false`, the placeholder will *never* float
- If set to `null`, the placeholder will float if text is entered.
Closes #2466
---
src/demo-app/input/input-container-demo.html | 3 +-
src/lib/input/input-container.html | 2 +-
src/lib/input/input-container.spec.ts | 85 +++++++++++++++++++-
src/lib/input/input-container.ts | 20 ++++-
4 files changed, 103 insertions(+), 7 deletions(-)
diff --git a/src/demo-app/input/input-container-demo.html b/src/demo-app/input/input-container-demo.html
index d393a5b6459e..007a583dc878 100644
--- a/src/demo-app/input/input-container-demo.html
+++ b/src/demo-app/input/input-container-demo.html
@@ -180,7 +180,8 @@
Textarea
- Check to make floating label:
+ Toggle Floating Label
+
diff --git a/src/lib/input/input-container.html b/src/lib/input/input-container.html
index 50b76067a9c2..ce2bc748ff30 100644
--- a/src/lib/input/input-container.html
+++ b/src/lib/input/input-container.html
@@ -7,7 +7,7 @@
- Toggle Floating Label
-
+
+ Auto Float
+ Always Float
+ Never Float
+
+
+
+
-
+
diff --git a/src/demo-app/input/input-container-demo.ts b/src/demo-app/input/input-container-demo.ts
index 38edcda046a2..9c773f00e5ee 100644
--- a/src/demo-app/input/input-container-demo.ts
+++ b/src/demo-app/input/input-container-demo.ts
@@ -11,9 +11,9 @@ let max = 5;
styleUrls: ['input-container-demo.css'],
})
export class InputContainerDemo {
+ floatingLabel: string = 'auto';
dividerColor: boolean;
requiredField: boolean;
- floatingLabel: boolean;
ctrlDisabled = false;
name: string;
diff --git a/src/lib/input/input-container-errors.ts b/src/lib/input/input-container-errors.ts
index 90a9337b2a65..00864cdfec94 100644
--- a/src/lib/input/input-container-errors.ts
+++ b/src/lib/input/input-container-errors.ts
@@ -28,3 +28,9 @@ export class MdInputContainerMissingMdInputError extends MdError {
'to the native input or textarea element?');
}
}
+
+export class MdInputContainerFloatingPlaceholderInvalidError extends MdError {
+ constructor(value: string) {
+ super(`The value "${value}" for the floatingPlaceholder input is not valid.`);
+ }
+}
diff --git a/src/lib/input/input-container.html b/src/lib/input/input-container.html
index ce2bc748ff30..c457a7d8173c 100644
--- a/src/lib/input/input-container.html
+++ b/src/lib/input/input-container.html
@@ -9,7 +9,7 @@
[attr.for]="_mdInputChild.id"
[class.md-empty]="_mdInputChild.empty && !_shouldAlwaysFloat"
[class.md-focused]="_mdInputChild.focused"
- [class.md-float]="floatingPlaceholder"
+ [class.md-float]="_canPlaceholderFloat"
[class.md-accent]="dividerColor == 'accent'"
[class.md-warn]="dividerColor == 'warn'"
*ngIf="_hasPlaceholder()">
diff --git a/src/lib/input/input-container.spec.ts b/src/lib/input/input-container.spec.ts
index 0b244626850e..eea31125d4e8 100644
--- a/src/lib/input/input-container.spec.ts
+++ b/src/lib/input/input-container.spec.ts
@@ -62,8 +62,8 @@ describe('MdInputContainer', function () {
let inputContainer = fixture.debugElement.query(By.directive(MdInputContainer))
.componentInstance as MdInputContainer;
- expect(inputContainer.floatingPlaceholder).toBe(true,
- 'Expected MdInputContainer to default to having floating placeholders turned on');
+ expect(inputContainer.floatingPlaceholder).toBe('auto',
+ 'Expected MdInputContainer to set floatingLabel to auto by default.');
});
it('should not be treated as empty if type is date',
@@ -483,20 +483,20 @@ describe('MdInputContainer', function () {
let fixture = TestBed.createComponent(MdInputContainerWithDynamicPlaceholder);
fixture.detectChanges();
- let inputEl = fixture.debugElement.query(By.css('input'));
+ let inputEl = fixture.debugElement.query(By.css('input')).nativeElement;
let labelEl = fixture.debugElement.query(By.css('label')).nativeElement;
expect(labelEl.classList).not.toContain('md-empty');
expect(labelEl.classList).toContain('md-float');
- fixture.componentInstance.shouldFloat = null;
+ fixture.componentInstance.shouldFloat = 'auto';
fixture.detectChanges();
expect(labelEl.classList).toContain('md-empty');
expect(labelEl.classList).toContain('md-float');
// Update the value of the input.
- inputEl.nativeElement.value = 'Text';
+ inputEl.value = 'Text';
// Fake behavior of the `(input)` event which should trigger a change detection.
fixture.detectChanges();
@@ -509,7 +509,7 @@ describe('MdInputContainer', function () {
let fixture = TestBed.createComponent(MdInputContainerWithDynamicPlaceholder);
fixture.detectChanges();
- let inputEl = fixture.debugElement.query(By.css('input'));
+ let inputEl = fixture.debugElement.query(By.css('input')).nativeElement;
let labelEl = fixture.debugElement.query(By.css('label')).nativeElement;
expect(labelEl.classList).not.toContain('md-empty');
@@ -518,7 +518,7 @@ describe('MdInputContainer', function () {
fixture.detectChanges();
// Update the value of the input.
- inputEl.nativeElement.value = 'Text';
+ inputEl.value = 'Text';
// Fake behavior of the `(input)` event which should trigger a change detection.
fixture.detectChanges();
@@ -531,17 +531,17 @@ describe('MdInputContainer', function () {
it('should never float the placeholder when floatingPlaceholder is set to false', () => {
let fixture = TestBed.createComponent(MdInputContainerWithDynamicPlaceholder);
- fixture.componentInstance.shouldFloat = false;
+ fixture.componentInstance.shouldFloat = 'never';
fixture.detectChanges();
- let inputEl = fixture.debugElement.query(By.css('input'));
+ let inputEl = fixture.debugElement.query(By.css('input')).nativeElement;
let labelEl = fixture.debugElement.query(By.css('label')).nativeElement;
expect(labelEl.classList).toContain('md-empty');
expect(labelEl.classList).not.toContain('md-float');
// Update the value of the input.
- inputEl.nativeElement.value = 'Text';
+ inputEl.value = 'Text';
// Fake behavior of the `(input)` event which should trigger a change detection.
fixture.detectChanges();
@@ -741,7 +741,7 @@ class MdInputContainerWithValueBinding {
@Component({
template: `
-
+
`
@@ -755,7 +755,7 @@ class MdInputContainerWithStaticPlaceholder {}
`
})
class MdInputContainerWithDynamicPlaceholder {
- shouldFloat: boolean = true;
+ shouldFloat: string = 'always';
}
@Component({
diff --git a/src/lib/input/input-container.ts b/src/lib/input/input-container.ts
index 814b754e15b9..9e3f59cf4566 100644
--- a/src/lib/input/input-container.ts
+++ b/src/lib/input/input-container.ts
@@ -20,7 +20,7 @@ import {
MdInputContainerUnsupportedTypeError,
MdInputContainerPlaceholderConflictError,
MdInputContainerDuplicatedHintError,
- MdInputContainerMissingMdInputError
+ MdInputContainerMissingMdInputError, MdInputContainerFloatingPlaceholderInvalidError
} from './input-container-errors';
@@ -38,6 +38,9 @@ const MD_INPUT_INVALID_TYPES = [
'submit'
];
+/** Valid options for the floatingPlaceholder input binding. */
+export type MD_INPUT_PLACEHOLDER_TYPES = 'always' | 'never' | 'auto';
+const MD_INPUT_PLACEHOLDER_VALUES = ['always', 'never', 'auto'];
let nextUniqueId = 0;
@@ -254,11 +257,10 @@ export class MdInputContainer implements AfterContentInit {
@Input() dividerColor: 'primary' | 'accent' | 'warn' = 'primary';
/** Whether the floating label should always float or not. */
- _shouldAlwaysFloat: boolean = false;
+ get _shouldAlwaysFloat() { return this._floatingPlaceholder === 'always'; };
/** Whether the placeholder can float or not. */
- _floatingPlaceholder: boolean = true;
-
+ get _canPlaceholderFloat() { return this._floatingPlaceholder !== 'never'; }
/** Text for the input hint. */
@Input()
@@ -273,15 +275,17 @@ export class MdInputContainer implements AfterContentInit {
_hintLabelId: string = `md-input-hint-${nextUniqueId++}`;
/**
- * Whether the placeholder should always float or just show the placeholder when empty.
- * If the value is set to null the placeholder will float if text is entered.
+ * Whether the placeholder should always float, never float or float as the user types.
*/
@Input()
get floatingPlaceholder() { return this._floatingPlaceholder; }
- set floatingPlaceholder(value: boolean) {
- this._floatingPlaceholder = value == null || coerceBooleanProperty(value);
- this._shouldAlwaysFloat = coerceBooleanProperty(value);
+ set floatingPlaceholder(value: MD_INPUT_PLACEHOLDER_TYPES) {
+ if (value && MD_INPUT_PLACEHOLDER_VALUES.indexOf(value) === -1) {
+ throw new MdInputContainerFloatingPlaceholderInvalidError(value);
+ }
+ this._floatingPlaceholder = value || 'auto';
}
+ private _floatingPlaceholder: MD_INPUT_PLACEHOLDER_TYPES = 'auto';
@ContentChild(MdInputDirective) _mdInputChild: MdInputDirective;
diff --git a/src/lib/input/input.md b/src/lib/input/input.md
index ebd0750035f8..40a768863c51 100644
--- a/src/lib/input/input.md
+++ b/src/lib/input/input.md
@@ -38,9 +38,11 @@ be used with `md-input-container`:
A placeholder is an indicative text displayed in the input zone when the input does not contain
text. When text is present, the indicative text will float above this input zone.
-The `floatingPlaceholder` attribute of `md-input-container` can be set to `false` to hide the
+The `floatingPlaceholder` attribute of `md-input-container` can be set to `never` to hide the
indicative text instead when text is present in the input.
+When setting `floatingPlaceholder` to `always` the floating label will always show above the input.
+
A placeholder for the input can be specified in one of two ways: either using the `placeholder`
attribute on the `input` or `textarea`, or using an `md-placeholder` element in the
`md-input-container`. Using both will raise an error.
From 066c3d641155116b22468420b0d2f63b6aa489fb Mon Sep 17 00:00:00 2001
From: Paul Gschwendtner
Date: Sat, 14 Jan 2017 16:12:54 +0100
Subject: [PATCH 3/4] Single line comment
---
src/lib/input/input-container.ts | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/lib/input/input-container.ts b/src/lib/input/input-container.ts
index 9e3f59cf4566..84b221eea87f 100644
--- a/src/lib/input/input-container.ts
+++ b/src/lib/input/input-container.ts
@@ -274,9 +274,7 @@ export class MdInputContainer implements AfterContentInit {
// Unique id for the hint label.
_hintLabelId: string = `md-input-hint-${nextUniqueId++}`;
- /**
- * Whether the placeholder should always float, never float or float as the user types.
- */
+ /** Whether the placeholder should always float, never float or float as the user types. */
@Input()
get floatingPlaceholder() { return this._floatingPlaceholder; }
set floatingPlaceholder(value: MD_INPUT_PLACEHOLDER_TYPES) {
From 025fae47a7387a0aebc6fb000a1c3401b45ddda2 Mon Sep 17 00:00:00 2001
From: Paul Gschwendtner
Date: Fri, 27 Jan 2017 22:20:19 +0100
Subject: [PATCH 4/4] Address comments
---
src/demo-app/input/input-container-demo.html | 2 +-
src/lib/input/input-container-errors.ts | 6 ------
src/lib/input/input-container.spec.ts | 14 ++++++-------
src/lib/input/input-container.ts | 22 ++++++++------------
src/lib/input/input.md | 4 ++--
5 files changed, 19 insertions(+), 29 deletions(-)
diff --git a/src/demo-app/input/input-container-demo.html b/src/demo-app/input/input-container-demo.html
index 3d29303032b5..d73c0cbb0aa6 100644
--- a/src/demo-app/input/input-container-demo.html
+++ b/src/demo-app/input/input-container-demo.html
@@ -188,7 +188,7 @@
Textarea
-
+
diff --git a/src/lib/input/input-container-errors.ts b/src/lib/input/input-container-errors.ts
index 00864cdfec94..90a9337b2a65 100644
--- a/src/lib/input/input-container-errors.ts
+++ b/src/lib/input/input-container-errors.ts
@@ -28,9 +28,3 @@ export class MdInputContainerMissingMdInputError extends MdError {
'to the native input or textarea element?');
}
}
-
-export class MdInputContainerFloatingPlaceholderInvalidError extends MdError {
- constructor(value: string) {
- super(`The value "${value}" for the floatingPlaceholder input is not valid.`);
- }
-}
diff --git a/src/lib/input/input-container.spec.ts b/src/lib/input/input-container.spec.ts
index eea31125d4e8..953c7e57c353 100644
--- a/src/lib/input/input-container.spec.ts
+++ b/src/lib/input/input-container.spec.ts
@@ -62,7 +62,7 @@ describe('MdInputContainer', function () {
let inputContainer = fixture.debugElement.query(By.directive(MdInputContainer))
.componentInstance as MdInputContainer;
- expect(inputContainer.floatingPlaceholder).toBe('auto',
+ expect(inputContainer.floatPlaceholder).toBe('auto',
'Expected MdInputContainer to set floatingLabel to auto by default.');
});
@@ -479,7 +479,7 @@ describe('MdInputContainer', function () {
expect(ariaValue).toBe(`${hintLabel.getAttribute('id')} ${endLabel.getAttribute('id')}`);
});
- it('should float when floatingPlaceholder is set to default and text is entered', () => {
+ it('should float when floatPlaceholder is set to default and text is entered', () => {
let fixture = TestBed.createComponent(MdInputContainerWithDynamicPlaceholder);
fixture.detectChanges();
@@ -505,7 +505,7 @@ describe('MdInputContainer', function () {
expect(labelEl.classList).toContain('md-float');
});
- it('should always float the placeholder when floatingPlaceholder is set to true', () => {
+ it('should always float the placeholder when floatPlaceholder is set to true', () => {
let fixture = TestBed.createComponent(MdInputContainerWithDynamicPlaceholder);
fixture.detectChanges();
@@ -528,7 +528,7 @@ describe('MdInputContainer', function () {
});
- it('should never float the placeholder when floatingPlaceholder is set to false', () => {
+ it('should never float the placeholder when floatPlaceholder is set to false', () => {
let fixture = TestBed.createComponent(MdInputContainerWithDynamicPlaceholder);
fixture.componentInstance.shouldFloat = 'never';
@@ -741,7 +741,7 @@ class MdInputContainerWithValueBinding {
@Component({
template: `
-
+
`
@@ -750,8 +750,8 @@ class MdInputContainerWithStaticPlaceholder {}
@Component({
template: `
-
-
+
+
`
})
class MdInputContainerWithDynamicPlaceholder {
diff --git a/src/lib/input/input-container.ts b/src/lib/input/input-container.ts
index 84b221eea87f..070cb8203263 100644
--- a/src/lib/input/input-container.ts
+++ b/src/lib/input/input-container.ts
@@ -20,7 +20,7 @@ import {
MdInputContainerUnsupportedTypeError,
MdInputContainerPlaceholderConflictError,
MdInputContainerDuplicatedHintError,
- MdInputContainerMissingMdInputError, MdInputContainerFloatingPlaceholderInvalidError
+ MdInputContainerMissingMdInputError
} from './input-container-errors';
@@ -38,9 +38,8 @@ const MD_INPUT_INVALID_TYPES = [
'submit'
];
-/** Valid options for the floatingPlaceholder input binding. */
-export type MD_INPUT_PLACEHOLDER_TYPES = 'always' | 'never' | 'auto';
-const MD_INPUT_PLACEHOLDER_VALUES = ['always', 'never', 'auto'];
+/** Type for the available floatPlaceholder values. */
+export type FloatPlaceholderType = 'always' | 'never' | 'auto';
let nextUniqueId = 0;
@@ -257,10 +256,10 @@ export class MdInputContainer implements AfterContentInit {
@Input() dividerColor: 'primary' | 'accent' | 'warn' = 'primary';
/** Whether the floating label should always float or not. */
- get _shouldAlwaysFloat() { return this._floatingPlaceholder === 'always'; };
+ get _shouldAlwaysFloat() { return this._floatPlaceholder === 'always'; };
/** Whether the placeholder can float or not. */
- get _canPlaceholderFloat() { return this._floatingPlaceholder !== 'never'; }
+ get _canPlaceholderFloat() { return this._floatPlaceholder !== 'never'; }
/** Text for the input hint. */
@Input()
@@ -276,14 +275,11 @@ export class MdInputContainer implements AfterContentInit {
/** Whether the placeholder should always float, never float or float as the user types. */
@Input()
- get floatingPlaceholder() { return this._floatingPlaceholder; }
- set floatingPlaceholder(value: MD_INPUT_PLACEHOLDER_TYPES) {
- if (value && MD_INPUT_PLACEHOLDER_VALUES.indexOf(value) === -1) {
- throw new MdInputContainerFloatingPlaceholderInvalidError(value);
- }
- this._floatingPlaceholder = value || 'auto';
+ get floatPlaceholder() { return this._floatPlaceholder; }
+ set floatPlaceholder(value: FloatPlaceholderType) {
+ this._floatPlaceholder = value || 'auto';
}
- private _floatingPlaceholder: MD_INPUT_PLACEHOLDER_TYPES = 'auto';
+ private _floatPlaceholder: FloatPlaceholderType = 'auto';
@ContentChild(MdInputDirective) _mdInputChild: MdInputDirective;
diff --git a/src/lib/input/input.md b/src/lib/input/input.md
index 40a768863c51..9e17b3baf7bb 100644
--- a/src/lib/input/input.md
+++ b/src/lib/input/input.md
@@ -38,10 +38,10 @@ be used with `md-input-container`:
A placeholder is an indicative text displayed in the input zone when the input does not contain
text. When text is present, the indicative text will float above this input zone.
-The `floatingPlaceholder` attribute of `md-input-container` can be set to `never` to hide the
+The `floatPlaceholder` attribute of `md-input-container` can be set to `never` to hide the
indicative text instead when text is present in the input.
-When setting `floatingPlaceholder` to `always` the floating label will always show above the input.
+When setting `floatPlaceholder` to `always` the floating label will always show above the input.
A placeholder for the input can be specified in one of two ways: either using the `placeholder`
attribute on the `input` or `textarea`, or using an `md-placeholder` element in the