Skip to content

Commit

Permalink
feat(textarea): initial md-textarea (#1562)
Browse files Browse the repository at this point in the history
  • Loading branch information
fxck authored and jelbourn committed Oct 27, 2016
1 parent ce26cae commit aff22e5
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 11 deletions.
21 changes: 19 additions & 2 deletions src/demo-app/input/input-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
<td><md-input placeholder="Long Last Name That Will Be Truncated" style="width: 100%"></md-input></td>
</tr></table>
<p>
<md-input class="demo-full-width" placeholder="Address" value="1600 Amphitheatre Pkway"></md-input>
<md-input class="demo-full-width" placeholder="Address 2"></md-input>
<md-textarea class="demo-full-width" placeholder="Address" value="1600 Amphitheatre Pkway"></md-textarea>
<md-textarea class="demo-full-width" placeholder="Address 2"></md-textarea>
</p>
<table style="width: 100%" cellspacing="0"><tr>
<td><md-input class="demo-full-width" placeholder="City" value="Mountain View"></md-input></td>
Expand Down Expand Up @@ -39,22 +39,39 @@
<md-card class="demo-card demo-basic">
<md-toolbar color="primary">Divider Colors</md-toolbar>
<md-card-content>
<h4>Input</h4>
<md-input dividerColor="primary" placeholder="Default Color" value="example"></md-input>
<md-input dividerColor="accent" placeholder="Accent Color" value="example"></md-input>
<md-input dividerColor="warn" placeholder="Warn Color" value="example"></md-input>

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

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

<md-card class="demo-card demo-basic">
<md-toolbar color="primary">Hints</md-toolbar>
<md-card-content>
<h4>Input</h4>
<p>
<md-input placeholder="Character count (100 max)" maxLength="100" class="demo-full-width"
value="Hello world. How are you?"
#characterCountHintExample>
<md-hint align="end">{{characterCountHintExample.characterCount}} / 100</md-hint>
</md-input>
</p>

<h4>Textarea</h4>
<p>
<md-textarea placeholder="Character count (100 max)" maxLength="100" class="demo-full-width"
value="Hello world. How are you?"
#characterCountHintExample>
<md-hint align="end">{{characterCountHintExample.characterCount}} / 100</md-hint>
</md-textarea>
</p>
</md-card-content>
</md-card>

Expand Down
1 change: 1 addition & 0 deletions src/demo-app/input/input-demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export class InputDemo {
{ value: 40 },
{ value: 50 },
];
rows = 8;

addABunch(n: number) {
for (let x = 0; x < n; x++) {
Expand Down
18 changes: 13 additions & 5 deletions src/lib/input/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# mdInput
# mdInput / mdTextarea

Inputs are the basic input component of Material 2. The spec can be found [here](https://www.google.com/design/spec/components/text-fields.html).



## Notes
* The `<md-input>` component fully support two-way binding of `ngModel`, as if it was a normal `<input>`.
* The `<md-input>` / `<md-textara>` component fully support two-way binding of `ngModel`, as if it was a normal `<input>` and `<textarea>`.



Expand All @@ -18,7 +18,7 @@ The valid `type` attribute values are any supported by your browser, with the ex

## Placeholder

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.
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.

You can set the `floatingPlaceholder` attribute to `false` to hide the indicative text instead when text is present in the input.

Expand Down Expand Up @@ -106,6 +106,14 @@ export class MyComponent implements OnInit {
}
```

## Textareas

```html
<md-textarea placeholder="Textarea with autosize"></md-textarea>
```

### Example

## Full Forms

You can make a full form using inputs, and it will support autofill natively.
Expand All @@ -125,8 +133,8 @@ You can make a full form using inputs, and it will support autofill natively.
<td><md-input placeholder="Long Last Name That Will Be Truncated" style="width: 100%"></md-input></td>
</tr></table>
<p>
<md-input class="demo-full-width" placeholder="Address" value="1600 Amphitheatre Pkway"></md-input>
<md-input class="demo-full-width" placeholder="Address 2"></md-input>
<md-textarea class="demo-full-width" placeholder="Address" value="1600 Amphitheatre Pkway"></md-textarea>
<md-textarea class="demo-full-width" placeholder="Address 2"></md-textarea>
</p>
<table style="width: 100%" cellspacing="0"><tr>
<td><md-input class="demo-full-width" placeholder="City"></md-input></td>
Expand Down
32 changes: 32 additions & 0 deletions src/lib/input/input.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

<div class="md-input-infix">
<input #input
*ngIf="_elementType === 'input'"
class="md-input-element"
[class.md-end]="align == 'end'"
[attr.aria-label]="ariaLabel"
Expand Down Expand Up @@ -34,6 +35,37 @@
[(ngModel)]="value"
(change)="_handleChange($event)">

<textarea
#input
*ngIf="_elementType === 'textarea'"
class="md-input-element md-input-element-textarea"
[class.md-end]="align == 'end'"
[attr.aria-label]="ariaLabel"
[attr.aria-labelledby]="ariaLabelledBy"
[attr.aria-disabled]="ariaDisabled"
[attr.aria-required]="ariaRequired"
[attr.aria-invalid]="ariaInvalid"
[attr.autocomplete]="autocomplete"
[attr.autocapitalize]="autocapitalize"
[attr.cols]="cols"
[attr.rows]="rows"
[attr.wrap]="wrap"
[autofocus]="autofocus"
[disabled]="disabled"
[id]="inputId"
[attr.maxlength]="maxlength"
[attr.minlength]="minlength"
[readonly]="readonly"
[required]="required"
[spellcheck]="spellcheck"
[attr.tabindex]="tabindex"
[attr.name]="name"
(focus)="_handleFocus($event)"
(blur)="_handleBlur($event)"
[(ngModel)]="value"
(change)="_handleChange($event)"></textarea>


<label class="md-input-placeholder"
[attr.for]="inputId"
[class.md-empty]="empty"
Expand Down
2 changes: 1 addition & 1 deletion src/lib/input/input.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ $md-input-underline-disabled-background-image:
width: 100% / $md-input-floating-placeholder-scale-factor;
}

md-input {
md-input, md-textarea {
display: inline-block;
position: relative;
font-family: $md-font-family;
Expand Down
27 changes: 26 additions & 1 deletion src/lib/input/input.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ describe('MdInput', function () {
MdInputTextTestController,
MdInputPasswordTestController,
MdInputNumberTestController,
MdTextareaWithBindings,
],
});

Expand Down Expand Up @@ -611,12 +612,28 @@ describe('MdInput', function () {

it('supports a name attribute', () => {
let fixture = TestBed.createComponent(MdInputWithNameTestController);

fixture.detectChanges();

const inputElement: HTMLInputElement = fixture.debugElement.query(By.css('input'))
.nativeElement;
fixture.detectChanges();

expect(inputElement.name).toBe('some-name');
});

describe('md-textarea', () => {
it('supports the rows, cols, and wrap attributes', () => {
let fixture = TestBed.createComponent(MdTextareaWithBindings);

fixture.detectChanges();

const textarea: HTMLTextAreaElement = fixture.nativeElement.querySelector('textarea');
expect(textarea.rows).toBe(4);
expect(textarea.cols).toBe(8);
expect(textarea.wrap).toBe('hard');
});
});

});

@Component({template: `<md-input id="test-id"></md-input>`})
Expand Down Expand Up @@ -789,3 +806,11 @@ class MdInputPasswordTestController {
class MdInputNumberTestController {
placeholder: string = '';
}

@Component({template:
`<md-textarea [rows]="rows" [cols]="cols" [wrap]="wrap" placeholder="Snacks"></md-textarea>`})
class MdTextareaWithBindings {
rows: number = 4;
cols: number = 8;
wrap: string = 'hard';
}
18 changes: 16 additions & 2 deletions src/lib/input/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {Observable} from 'rxjs/Observable';

const noop = () => {};


export const MD_INPUT_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MdInput),
Expand Down Expand Up @@ -86,14 +87,13 @@ export class MdHint {
@Input() align: 'start' | 'end' = 'start';
}


/**
* Component that represents a text input. It encapsulates the <input> HTMLElement and
* improve on its behaviour, along with styling it according to the Material Design.
*/
@Component({
moduleId: module.id,
selector: 'md-input',
selector: 'md-input, md-textarea',
templateUrl: 'input.html',
styleUrls: ['input.css'],
providers: [MD_INPUT_CONTROL_VALUE_ACCESSOR],
Expand Down Expand Up @@ -167,6 +167,11 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
@Input() type: string = 'text';
@Input() name: string = null;

// textarea-specific
@Input() rows: number = null;
@Input() cols: number = null;
@Input() wrap: 'soft' | 'hard' = null;

private _floatingPlaceholder: boolean = true;
private _autofocus: boolean = false;
private _disabled: boolean = false;
Expand Down Expand Up @@ -229,6 +234,15 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange

@ViewChild('input') _inputElement: ElementRef;

_elementType: 'input' | 'textarea';

constructor(elementRef: ElementRef) {
// Set the element type depending on normalized selector used(md-input / md-textarea)
this._elementType = elementRef.nativeElement.nodeName.toLowerCase() === 'md-input' ?
'input' :
'textarea';
}

/** Set focus on input */
focus() {
this._inputElement.nativeElement.focus();
Expand Down

0 comments on commit aff22e5

Please sign in to comment.