Skip to content

Commit

Permalink
feat(md-input): add back placeholder as a portal directive
Browse files Browse the repository at this point in the history
  • Loading branch information
hansl committed Nov 17, 2016
1 parent 9e80283 commit 691f295
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 38 deletions.
30 changes: 30 additions & 0 deletions src/demo-app/input/input-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,33 @@
</p>
</md-card-content>
</md-card>

<md-card class="demo-card demo-basic">
<md-toolbar color="primary">Divider Colors</md-toolbar>
<md-card-content>
<h4>Input</h4>
<input md-input dividerColor="primary" placeholder="Default Color">
<input md-input dividerColor="accent" placeholder="Accent Color">
<input md-input dividerColor="warn" placeholder="Warn Color">

<h4>Textarea</h4>
<textarea md-textarea dividerColor="primary" placeholder="Default Color"></textarea>
<textarea md-textarea dividerColor="accent" placeholder="Accent Color"></textarea>
<textarea md-textarea dividerColor="warn" placeholder="Warn Color"></textarea>

</md-card-content>
</md-card>

<md-card class="demo-card">
<md-toolbar color="primary">Placeholder Templates</md-toolbar>

<md-card-content>
<p>
<input md-input [placeholder]="placeholderTemplate1">

<template #placeholderTemplate1>
Example of a <b>placeholder</b> template
</template>
</p>
</md-card-content>
</md-card>
4 changes: 2 additions & 2 deletions src/lib/input/_input-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
$input-underline-disabled-color: md-color($foreground, hint-text);
$input-underline-focused-color: md-color($primary);

.md-input-placeholder {
.md-placeholder {
color: $input-placeholder-color;

// :focus is applied to the input, but we apply md-focused to the other elements
Expand All @@ -39,7 +39,7 @@
}

// See md-input-placeholder-floating mixin in input.scss
.md-input-wrapper input:-webkit-autofill + .md-input-placeholder, .md-input-placeholder.md-float.md-focused {
.md-input-wrapper input:-webkit-autofill + .md-placeholder, .md-placeholder.md-float.md-focused {

.md-placeholder-required {
color: $input-required-placeholder-color;
Expand Down
26 changes: 26 additions & 0 deletions src/lib/input/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,27 @@
import {CommonModule} from '@angular/common';
import {ModuleWithProviders, NgModule} from '@angular/core';

import {ProjectionModule, PortalModule} from '../core';

import {MdInput} from './input';
import {MdPlaceholder, MdPlaceholderContent} from './placeholder';


export * from './input';
export * from './placeholder';


@NgModule({
declarations: [MdPlaceholderContent, MdPlaceholder, MdInput],
imports: [PortalModule, ProjectionModule, CommonModule],
exports: [MdPlaceholder, MdInput],
entryComponents: [MdPlaceholderContent]
})
export class MdInputModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: MdInputModule,
providers: []
};
}
}
5 changes: 4 additions & 1 deletion src/lib/input/input.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
<dom-projection-host></dom-projection-host>
</div>

<div class="md-input-suffix"><template [ngTemplateOutlet]="_suffixTemplate()"></template></div>
<div class="md-input-suffix">
<template #suffixWrapper portalHost></template>
<template [ngTemplateOutlet]="_suffixTemplate()"></template>
</div>
<template #suffix>{{mdSuffix}}</template>
</div>

Expand Down
18 changes: 9 additions & 9 deletions src/lib/input/input.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
@import '../core/style/form-common';


$md-input-floating-placeholder-scale-factor: 0.75 !default;
$md-floating-placeholder-scale-factor: 0.75 !default;

// Gradient for showing the dashed line when the input is disabled.
$md-input-underline-disabled-background-image:
linear-gradient(to right, rgba(0, 0, 0, 0.26) 0%, rgba(0, 0, 0, 0.26) 33%, transparent 0%);

// Applies a floating placeholder above the input itself.
@mixin md-input-placeholder-floating {
@mixin md-placeholder-floating {
display: block;
padding-bottom: 5px;
transform: translateY(-100%) scale($md-input-floating-placeholder-scale-factor);
width: 100% / $md-input-floating-placeholder-scale-factor;
transform: translateY(-100%) scale($md-floating-placeholder-scale-factor);
width: 100% / $md-floating-placeholder-scale-factor;
}

.md-input-wrapper {
Expand Down Expand Up @@ -57,7 +57,7 @@ $md-input-underline-disabled-background-image:
}

// The Input element proper.
input[md-input], textarea[md-input] {
input[md-input], textarea[md-textarea] {
// Font needs to be inherited, because by default <input> has a system font.
font: inherit;

Expand Down Expand Up @@ -93,15 +93,15 @@ input[md-input], textarea[md-input] {
// Once the autofill is committed, a change event happen and the regular md-input
// classes take over to fulfill this behaviour.
// Assumes the autofill is non-empty.
&:-webkit-autofill + .md-input-placeholder.md-float {
@include md-input-placeholder-floating;
&:-webkit-autofill + .md-placeholder.md-float {
@include md-placeholder-floating;
}
}

// The placeholder label. This is invisible unless it is. The logic to show it is
// basically `empty || (float && (!empty || focused))`. Float is dependent on the
// `floatingPlaceholder` input.
.md-input-placeholder {
.md-placeholder {
// The placeholder is after the <input>, but needs to be aligned top-left of the
// infix <div>.
position: absolute;
Expand Down Expand Up @@ -133,7 +133,7 @@ input[md-input], textarea[md-input] {

// Show the placeholder above the input when it's not empty, or focused.
&.md-float:not(.md-empty), &.md-float.md-focused {
@include md-input-placeholder-floating;
@include md-placeholder-floating;
}

[dir='rtl'] & {
Expand Down
17 changes: 13 additions & 4 deletions src/lib/input/input.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
import {Component} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {By} from '@angular/platform-browser';
import {MdInput, MdInputModule} from './input';
import {MdInput, MdInputModule} from './index';
import {ProjectionModule} from '../core/projection/projection';

describe('MdInput', function () {
Expand Down Expand Up @@ -34,8 +34,8 @@ describe('MdInput', function () {
// TODO(kara): update when core/testing adds fix
it('support ngModel', async(() => {
let fixture = TestBed.createComponent(MdInputBaseTestController);

fixture.detectChanges();

let instance = fixture.componentInstance;
let el: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;

Expand All @@ -61,8 +61,9 @@ describe('MdInput', function () {

it('counts characters', async(() => {
let fixture = TestBed.createComponent(MdInputBaseTestController);
let instance = fixture.componentInstance;
fixture.detectChanges();

let instance = fixture.componentInstance;
let inputInstance = fixture.debugElement.query(By.directive(MdInput)).componentInstance;
expect(inputInstance.characterCount).toEqual(0);

Expand Down Expand Up @@ -95,7 +96,6 @@ describe('MdInput', function () {
expect(textarea.wrap).toBe('hard');
});
});

});

@Component({template: `<input md-input type="number" class="test-class" style="color: 123456">`})
Expand All @@ -107,6 +107,15 @@ class MdInputNumberTypeConservedTestComponent {
value: number = 0;
}

@Component({template: `<input md-input placeholder="string placeholder">`})
class MdInputPlaceholderStringTestController { }

@Component({template: `
<input md-input [placeholder]="p">
<template #p>template placeholder</template>
`})
class MdInputPlaceholderTemplateTestController { }

@Component({template: `<input md-input type="file">`})
class MdInputInvalidTypeTestController { }

Expand Down
32 changes: 10 additions & 22 deletions src/lib/input/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,20 @@ import {
ViewChild,
ElementRef,
OnInit,
NgModule,
ModuleWithProviders,
ViewEncapsulation,
HostListener,
TemplateRef,
TemplateRef, forwardRef,
} from '@angular/core';
import {CommonModule} from '@angular/common';
import {DomSanitizer, SafeStyle} from '@angular/platform-browser';
import {
ProjectionModule,
DomProjection,
DomProjectionHost,
MdError,
coerceBooleanProperty
} from '../core';
import {MD_PLACEHOLDER_HOST_TOKEN, MdPlaceholderHost} from './placeholder';
import {PortalHost} from '../core/portal/portal';
import {PortalHostDirective} from '../core/portal/portal-directives';


export class MdInputUnsupportedTypeError extends MdError {
Expand All @@ -46,6 +45,9 @@ const MD_INPUT_INVALID_INPUT_TYPE = [
templateUrl: 'input.html',
styleUrls: ['input.css'],
encapsulation: ViewEncapsulation.None,
providers: [
{ provide: MD_PLACEHOLDER_HOST_TOKEN, useExisting: forwardRef(() => MdInput) }
],
host: {
// This is to remove the properties of the `input md-input` itself. We still want to use them
// as an @Input though, so we use HostBinding.
Expand All @@ -54,10 +56,12 @@ const MD_INPUT_INVALID_INPUT_TYPE = [
'attr.align': ''
}
})
export class MdInput implements OnInit {
export class MdInput implements OnInit, MdPlaceholderHost {
@ViewChild(DomProjectionHost) _host: DomProjectionHost;
@ViewChild('suffix') _suffix: TemplateRef<any>;
@ViewChild('prefix') _prefix: TemplateRef<any>;

@ViewChild('suffixWrapper', { read: PortalHostDirective }) suffixPortalHost: PortalHost;
private _focused: boolean = false;

@Input('class') _cssClass: string = '';
Expand Down Expand Up @@ -122,7 +126,6 @@ export class MdInput implements OnInit {
@Input() mdPrefix: string | TemplateRef<any>;
@Input() mdSuffix: string | TemplateRef<any>;


@HostListener('focus') _onFocus() {
this._focused = true;
}
Expand All @@ -134,18 +137,3 @@ export class MdInput implements OnInit {
this._ref.nativeElement.focus();
}
}


@NgModule({
declarations: [MdInput],
imports: [ProjectionModule, CommonModule],
exports: [MdInput],
})
export class MdInputModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: MdInputModule,
providers: []
};
}
}
12 changes: 12 additions & 0 deletions src/lib/input/placeholder.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<label class="md-placeholder"
[attr.for]="placeholder?.inputId"
[class.md-empty]="placeholder?.empty"
[class.md-focused]="placeholder?._focused"
[class.md-float]="placeholder?._floatingPlaceholder"
[class.md-accent]="placeholder?.dividerColor == 'accent'"
[class.md-warn]="placeholder?.dividerColor == 'warn'">
<template [ngTemplateOutlet]="_template()"></template>
<span class="md-placeholder-required" *ngIf="placeholder?._required">*</span>
</label>

<template #stringTemplate>{{content}}</template>
2 changes: 2 additions & 0 deletions src/lib/input/placeholder.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@


39 changes: 39 additions & 0 deletions src/lib/input/placeholder.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {
async,
TestBed,
} from '@angular/core/testing';
import {Component} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {By} from '@angular/platform-browser';
import {MdInput, MdInputModule} from './index';
import {ProjectionModule} from '../core/projection/projection';

fdescribe('MdPlaceholder', function () {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MdInputModule.forRoot(), FormsModule, ProjectionModule.forRoot()],
declarations: [
MdPlaceholderStringTestController,
MdPlaceholderTemplateTestController,
],
});

TestBed.compileComponents();
}));

it('works with string placeholder', () => {
let fixture = TestBed.createComponent(MdPlaceholderStringTestController);
fixture.detectChanges();
let el: HTMLElement = fixture.nativeElement;
console.log(el.innerHTML);
});
});

@Component({template: `<input md-input placeholder="string placeholder">`})
class MdPlaceholderStringTestController { }

@Component({template: `
<input md-input [placeholder]="p">
<template #p>template placeholder</template>
`})
class MdPlaceholderTemplateTestController { }
Loading

0 comments on commit 691f295

Please sign in to comment.