mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
* Implement global placeholder options so the default float option can be set to something other than 'auto' Fixes #4311
This commit is contained in:
committed by
Andrew Seguin
parent
66629cf1ed
commit
d0d79fd93a
@@ -103,6 +103,13 @@ export {MdCommonModule} from './common-behaviors/common-module';
|
||||
// Datetime
|
||||
export * from './datetime/index';
|
||||
|
||||
// Placeholder
|
||||
export {
|
||||
FloatPlaceholderType,
|
||||
PlaceholderOptions,
|
||||
MD_PLACEHOLDER_GLOBAL_OPTIONS
|
||||
} from './placeholder/placeholder-options';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
MdLineModule,
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { InjectionToken } from '@angular/core';
|
||||
|
||||
/** InjectionToken that can be used to specify the global placeholder options. */
|
||||
export const MD_PLACEHOLDER_GLOBAL_OPTIONS =
|
||||
new InjectionToken<PlaceholderOptions>('md-placeholder-global-options');
|
||||
|
||||
/** Type for the available floatPlaceholder values. */
|
||||
export type FloatPlaceholderType = 'always' | 'never' | 'auto';
|
||||
|
||||
export interface PlaceholderOptions {
|
||||
float?: FloatPlaceholderType;
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
getMdInputContainerMissingMdInputError,
|
||||
getMdInputContainerPlaceholderConflictError
|
||||
} from './input-container-errors';
|
||||
import {MD_PLACEHOLDER_GLOBAL_OPTIONS} from '../core/placeholder/placeholder-options';
|
||||
|
||||
|
||||
describe('MdInputContainer', function () {
|
||||
@@ -82,6 +83,29 @@ describe('MdInputContainer', function () {
|
||||
'Expected MdInputContainer to set floatingLabel to auto by default.');
|
||||
});
|
||||
|
||||
it('should default to global floating placeholder type', () => {
|
||||
TestBed.resetTestingModule();
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
FormsModule,
|
||||
MdInputModule,
|
||||
NoopAnimationsModule
|
||||
],
|
||||
declarations: [
|
||||
MdInputContainerBaseTestController
|
||||
],
|
||||
providers: [{ provide: MD_PLACEHOLDER_GLOBAL_OPTIONS, useValue: { float: 'always' } }]
|
||||
});
|
||||
|
||||
let fixture = TestBed.createComponent(MdInputContainerBaseTestController);
|
||||
fixture.detectChanges();
|
||||
|
||||
let inputContainer = fixture.debugElement.query(By.directive(MdInputContainer))
|
||||
.componentInstance as MdInputContainer;
|
||||
expect(inputContainer.floatPlaceholder).toBe('always',
|
||||
'Expected MdInputContainer to set floatingLabel to always from global option.');
|
||||
});
|
||||
|
||||
it('should not be treated as empty if type is date',
|
||||
inject([Platform], (platform: Platform) => {
|
||||
if (!(platform.TRIDENT || platform.FIREFOX)) {
|
||||
|
||||
@@ -16,7 +16,8 @@ import {
|
||||
Renderer2,
|
||||
Self,
|
||||
ViewChild,
|
||||
ViewEncapsulation
|
||||
ViewEncapsulation,
|
||||
Inject
|
||||
} from '@angular/core';
|
||||
import {animate, state, style, transition, trigger} from '@angular/animations';
|
||||
import {coerceBooleanProperty} from '../core';
|
||||
@@ -28,7 +29,11 @@ import {
|
||||
getMdInputContainerPlaceholderConflictError,
|
||||
getMdInputContainerUnsupportedTypeError
|
||||
} from './input-container-errors';
|
||||
|
||||
import {
|
||||
FloatPlaceholderType,
|
||||
PlaceholderOptions,
|
||||
MD_PLACEHOLDER_GLOBAL_OPTIONS
|
||||
} from '../core/placeholder/placeholder-options';
|
||||
|
||||
// Invalid input type. Using one of these will throw an MdInputContainerUnsupportedTypeError.
|
||||
const MD_INPUT_INVALID_TYPES = [
|
||||
@@ -44,9 +49,6 @@ const MD_INPUT_INVALID_TYPES = [
|
||||
'submit'
|
||||
];
|
||||
|
||||
/** Type for the available floatPlaceholder values. */
|
||||
export type FloatPlaceholderType = 'always' | 'never' | 'auto';
|
||||
|
||||
let nextUniqueId = 0;
|
||||
|
||||
|
||||
@@ -302,7 +304,10 @@ export class MdInputDirective {
|
||||
},
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
|
||||
export class MdInputContainer implements AfterViewInit, AfterContentInit, AfterContentChecked {
|
||||
private _placeholderOptions: PlaceholderOptions;
|
||||
|
||||
/** Alignment of the input container's content. */
|
||||
@Input() align: 'start' | 'end' = 'start';
|
||||
|
||||
@@ -347,9 +352,9 @@ export class MdInputContainer implements AfterViewInit, AfterContentInit, AfterC
|
||||
@Input()
|
||||
get floatPlaceholder() { return this._floatPlaceholder; }
|
||||
set floatPlaceholder(value: FloatPlaceholderType) {
|
||||
this._floatPlaceholder = value || 'auto';
|
||||
this._floatPlaceholder = value || this._placeholderOptions.float || 'auto';
|
||||
}
|
||||
private _floatPlaceholder: FloatPlaceholderType = 'auto';
|
||||
private _floatPlaceholder: FloatPlaceholderType;
|
||||
|
||||
/** Reference to the input's underline element. */
|
||||
@ViewChild('underline') underlineRef: ElementRef;
|
||||
@@ -368,7 +373,13 @@ export class MdInputContainer implements AfterViewInit, AfterContentInit, AfterC
|
||||
|
||||
constructor(
|
||||
public _elementRef: ElementRef,
|
||||
private _changeDetectorRef: ChangeDetectorRef) { }
|
||||
private _changeDetectorRef: ChangeDetectorRef,
|
||||
@Optional() private _parentForm: NgForm,
|
||||
@Optional() private _parentFormGroup: FormGroupDirective,
|
||||
@Optional() @Inject(MD_PLACEHOLDER_GLOBAL_OPTIONS) placeholderOptions: PlaceholderOptions) {
|
||||
this._placeholderOptions = placeholderOptions ? placeholderOptions : {};
|
||||
this.floatPlaceholder = this._placeholderOptions.float || 'auto';
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
this._validateInputChild();
|
||||
|
||||
@@ -60,6 +60,22 @@ A placeholder for the input can be specified in one of two ways: either using th
|
||||
attribute on the `input` or `textarea`, or using an `md-placeholder` element in the
|
||||
`md-input-container`. Using both will raise an error.
|
||||
|
||||
Global default placeholder options can be specified by setting the `MD_PLACEHOLDER_GLOBAL_OPTIONS` provider. This setting will apply to all components that support the floating placeholder.
|
||||
|
||||
```ts
|
||||
@NgModule({
|
||||
providers: [
|
||||
{provide: MD_PLACEHOLDER_GLOBAL_OPTIONS, useValue: { float: 'always' }}
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
Here are the available global options:
|
||||
|
||||
| Name | Type | Values | Description |
|
||||
| --------------- | ------- | ------------------- | ----------------------------------------- |
|
||||
| float | string | auto, always, never | The default placeholder float behavior. |
|
||||
|
||||
### Prefix and Suffix
|
||||
|
||||
HTML can be included before, and after the input tag, as prefix or suffix. It will be underlined as
|
||||
|
||||
@@ -62,6 +62,22 @@ It's possible to turn off the placeholder's floating animation using the `floatP
|
||||
</md-select>
|
||||
```
|
||||
|
||||
Global default placeholder options can be specified by setting the `MD_PLACEHOLDER_GLOBAL_OPTIONS` provider. This setting will apply to all components that support the floating placeholder.
|
||||
|
||||
```ts
|
||||
@NgModule({
|
||||
providers: [
|
||||
{provide: MD_PLACEHOLDER_GLOBAL_OPTIONS, useValue: { float: 'always' }}
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
Here are the available global options:
|
||||
|
||||
| Name | Type | Values | Description |
|
||||
| --------------- | ------- | ------------------- | ----------------------------------------- |
|
||||
| float | string | auto, always, never | The default placeholder float behavior. |
|
||||
|
||||
#### Keyboard interaction:
|
||||
- <kbd>DOWN_ARROW</kbd>: Focus next option
|
||||
- <kbd>UP_ARROW</kbd>: Focus previous option
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import {MdSelectModule} from './index';
|
||||
import {OverlayContainer} from '../core/overlay/overlay-container';
|
||||
import {MdSelect, MdSelectFloatPlaceholderType} from './select';
|
||||
import {MdSelect} from './select';
|
||||
import {getMdSelectDynamicMultipleError, getMdSelectNonArrayValueError} from './select-errors';
|
||||
import {MdOption} from '../core/option/option';
|
||||
import {Dir} from '../core/rtl/dir';
|
||||
@@ -25,6 +25,10 @@ import {ViewportRuler} from '../core/overlay/position/viewport-ruler';
|
||||
import {dispatchFakeEvent, dispatchKeyboardEvent} from '../core/testing/dispatch-events';
|
||||
import {wrappedErrorMessage} from '../core/testing/wrapped-error-message';
|
||||
import {ScrollDispatcher} from '../core/overlay/scroll/scroll-dispatcher';
|
||||
import {
|
||||
FloatPlaceholderType,
|
||||
MD_PLACEHOLDER_GLOBAL_OPTIONS
|
||||
} from '../core/placeholder/placeholder-options';
|
||||
|
||||
|
||||
describe('MdSelect', () => {
|
||||
@@ -1798,6 +1802,30 @@ describe('MdSelect', () => {
|
||||
|
||||
expect(fixture.componentInstance.select._getPlaceholderAnimationState()).toBe('floating-ltr');
|
||||
});
|
||||
|
||||
it ('should default to global floating placeholder type', () => {
|
||||
fixture.destroy();
|
||||
|
||||
TestBed.resetTestingModule();
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
MdSelectModule,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
NoopAnimationsModule
|
||||
],
|
||||
declarations: [
|
||||
FloatPlaceholderSelect
|
||||
],
|
||||
providers: [{ provide: MD_PLACEHOLDER_GLOBAL_OPTIONS, useValue: { float: 'always' } }]
|
||||
});
|
||||
|
||||
fixture = TestBed.createComponent(FloatPlaceholderSelect);
|
||||
fixture.componentInstance.floatPlaceholder = null;
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.componentInstance.select.floatPlaceholder).toBe('always');
|
||||
});
|
||||
});
|
||||
|
||||
describe('with OnPush change detection', () => {
|
||||
@@ -2419,7 +2447,7 @@ class BasicSelectOnPushPreselected {
|
||||
`,
|
||||
})
|
||||
class FloatPlaceholderSelect {
|
||||
floatPlaceholder: MdSelectFloatPlaceholderType = 'auto';
|
||||
floatPlaceholder: FloatPlaceholderType = 'auto';
|
||||
control = new FormControl();
|
||||
foods: any[] = [
|
||||
{ value: 'steak-0', viewValue: 'Steak' },
|
||||
|
||||
+25
-16
@@ -16,6 +16,7 @@ import {
|
||||
ChangeDetectorRef,
|
||||
Attribute,
|
||||
OnInit,
|
||||
Inject
|
||||
} from '@angular/core';
|
||||
import {MdOption, MdOptionSelectionChange} from '../core/option/option';
|
||||
import {ENTER, SPACE, UP_ARROW, DOWN_ARROW, HOME, END} from '../core/keyboard/keycodes';
|
||||
@@ -36,7 +37,11 @@ import 'rxjs/add/operator/startWith';
|
||||
import 'rxjs/add/operator/filter';
|
||||
import {CanColor, mixinColor} from '../core/common-behaviors/color';
|
||||
import {CanDisable} from '../core/common-behaviors/disabled';
|
||||
|
||||
import {
|
||||
FloatPlaceholderType,
|
||||
PlaceholderOptions,
|
||||
MD_PLACEHOLDER_GLOBAL_OPTIONS}
|
||||
from '../core/placeholder/placeholder-options';
|
||||
|
||||
/**
|
||||
* The following style constants are necessary to save here in order
|
||||
@@ -94,16 +99,12 @@ export class MdSelectChange {
|
||||
constructor(public source: MdSelect, public value: any) { }
|
||||
}
|
||||
|
||||
/** Allowed values for the floatPlaceholder option. */
|
||||
export type MdSelectFloatPlaceholderType = 'always' | 'never' | 'auto';
|
||||
|
||||
// Boilerplate for applying mixins to MdSelect.
|
||||
export class MdSelectBase {
|
||||
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
|
||||
}
|
||||
export const _MdSelectMixinBase = mixinColor(MdSelectBase, 'primary');
|
||||
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'md-select, mat-select',
|
||||
@@ -170,6 +171,9 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
|
||||
/** Tab index for the element. */
|
||||
private _tabIndex: number;
|
||||
|
||||
/** Deals with configuring placeholder options */
|
||||
private _placeholderOptions: PlaceholderOptions;
|
||||
|
||||
/**
|
||||
* The width of the trigger. Must be saved to set the min width of the overlay panel
|
||||
* and the width of the selected value.
|
||||
@@ -275,11 +279,11 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
|
||||
|
||||
/** Whether to float the placeholder text. */
|
||||
@Input()
|
||||
get floatPlaceholder(): MdSelectFloatPlaceholderType { return this._floatPlaceholder; }
|
||||
set floatPlaceholder(value: MdSelectFloatPlaceholderType) {
|
||||
this._floatPlaceholder = value || 'auto';
|
||||
get floatPlaceholder(): FloatPlaceholderType { return this._floatPlaceholder; }
|
||||
set floatPlaceholder(value: FloatPlaceholderType) {
|
||||
this._floatPlaceholder = value || this._placeholderOptions.float || 'auto';
|
||||
}
|
||||
private _floatPlaceholder: MdSelectFloatPlaceholderType = 'auto';
|
||||
private _floatPlaceholder: FloatPlaceholderType;
|
||||
|
||||
/** Tab index for the select element. */
|
||||
@Input()
|
||||
@@ -310,13 +314,15 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
|
||||
/** Event emitted when the selected value has been changed by the user. */
|
||||
@Output() change: EventEmitter<MdSelectChange> = new EventEmitter<MdSelectChange>();
|
||||
|
||||
constructor(private _viewportRuler: ViewportRuler,
|
||||
private _changeDetectorRef: ChangeDetectorRef,
|
||||
renderer: Renderer2,
|
||||
elementRef: ElementRef,
|
||||
@Optional() private _dir: Dir,
|
||||
@Self() @Optional() public _control: NgControl,
|
||||
@Attribute('tabindex') tabIndex: string) {
|
||||
constructor(
|
||||
private _viewportRuler: ViewportRuler,
|
||||
private _changeDetectorRef: ChangeDetectorRef,
|
||||
renderer: Renderer2,
|
||||
elementRef: ElementRef,
|
||||
@Optional() private _dir: Dir,
|
||||
@Self() @Optional() public _control: NgControl,
|
||||
@Attribute('tabindex') tabIndex: string,
|
||||
@Optional() @Inject(MD_PLACEHOLDER_GLOBAL_OPTIONS) placeholderOptions: PlaceholderOptions) {
|
||||
super(renderer, elementRef);
|
||||
|
||||
if (this._control) {
|
||||
@@ -324,6 +330,9 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
|
||||
}
|
||||
|
||||
this._tabIndex = parseInt(tabIndex) || 0;
|
||||
|
||||
this._placeholderOptions = placeholderOptions ? placeholderOptions : {};
|
||||
this.floatPlaceholder = this._placeholderOptions.float || 'auto';
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
Reference in New Issue
Block a user