Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(textarea): add md-textarea element #1562

Merged
merged 15 commits into from
Oct 27, 2016
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just FYI: we're probably going to do away with these internal elements and content-project an input from the user.

#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>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove min, max, and autocorrect. They don't exist on <textarea>

We should add rows, cols, and wrap. Need to think about how rows interacts with autosize.

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/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