Skip to content

Commit 8453e51

Browse files
authoredJun 24, 2021
fix: detect textarea value changes for autosize (#134)
1 parent 6ca5d93 commit 8453e51

File tree

2 files changed

+48
-34
lines changed

2 files changed

+48
-34
lines changed
 

‎src/input/autosize.directive.ts

+29-23
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ import {
22
AfterViewInit,
33
Directive,
44
ElementRef,
5-
HostListener,
65
Input,
6+
OnDestroy,
77
} from '@angular/core';
8+
import { NgControl } from '@angular/forms';
9+
import { Subject } from 'rxjs';
10+
import { startWith, takeUntil } from 'rxjs/operators';
811

912
import { calcTextareaHeight } from './utils';
1013

@@ -22,23 +25,15 @@ export interface AutoSizeValue {
2225
* Directive to automatically resize a textarea to fit its content.
2326
*/
2427
@Directive({
25-
// tslint:disable-next-line: directive-selector
26-
selector: 'textarea[autosize]',
28+
selector:
29+
// tslint:disable-next-line: directive-selector
30+
'textarea[autosize][ngModel],textarea[autosize][formControl],textarea[autosize][formControlName]',
2731
exportAs: 'TextareaAutosize',
2832
})
29-
export class AutosizeDirective implements AfterViewInit {
33+
export class AutosizeDirective implements AfterViewInit, OnDestroy {
3034
private _autoSize: AutoSizeValue = DEFAULT_VALUE;
3135

32-
private textareaCalcStyle: {
33-
minHeight?: string;
34-
maxHeight?: string;
35-
height?: string;
36-
} = {};
37-
38-
@HostListener('input')
39-
onTextareaInput() {
40-
this.resizeTextarea();
41-
}
36+
private readonly destroy$$ = new Subject<void>();
4237

4338
@Input('autosize')
4439
get autoSize() {
@@ -53,21 +48,32 @@ export class AutosizeDirective implements AfterViewInit {
5348
this.resizeTextarea();
5449
}
5550

56-
constructor(protected elementRef: ElementRef<HTMLTextAreaElement>) {}
51+
constructor(
52+
private readonly elRef: ElementRef<HTMLTextAreaElement>,
53+
private readonly ngControl: NgControl,
54+
) {}
5755

5856
resizeTextarea() {
57+
const el = this.elRef.nativeElement;
5958
const autoSize = this._autoSize;
60-
this.textareaCalcStyle = calcTextareaHeight(
61-
this.elementRef.nativeElement,
62-
autoSize.minRows,
63-
autoSize.maxRows,
59+
Object.assign(
60+
el.style,
61+
calcTextareaHeight(
62+
el,
63+
autoSize.minRows ?? DEFAULT_VALUE.minRows,
64+
autoSize.maxRows || DEFAULT_VALUE.maxRows, // 0 is unacceptable
65+
),
6466
);
65-
this.elementRef.nativeElement.style.minHeight = this.textareaCalcStyle.minHeight;
66-
this.elementRef.nativeElement.style.maxHeight = this.textareaCalcStyle.maxHeight;
67-
this.elementRef.nativeElement.style.height = this.textareaCalcStyle.height;
6867
}
6968

7069
ngAfterViewInit() {
71-
this.resizeTextarea();
70+
this.ngControl.valueChanges
71+
.pipe(startWith(null as void), takeUntil(this.destroy$$))
72+
.subscribe(() => this.resizeTextarea());
73+
}
74+
75+
ngOnDestroy() {
76+
this.destroy$$.next();
77+
this.destroy$$.complete();
7278
}
7379
}

‎stories/input/index.ts

+19-11
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,6 @@ storiesOf('Input', module)
8888
<p style="margin-top: 26px;">
8989
Textarea with autosize (size:default = medium):
9090
</p>
91-
<textarea
92-
autosize
93-
aui-input
94-
placeholder="autosize default: 1 row"
95-
></textarea>
96-
<textarea
97-
[autosize]="{minRows:3,maxRows:10}"
98-
style="margin-top: 16px;"
99-
aui-input
100-
placeholder="autosize: min 3 rows, max 10 rows"
101-
></textarea>
10291
</div>
10392
`,
10493
}))
@@ -341,4 +330,23 @@ storiesOf('Input', module)
341330
controls,
342331
},
343332
};
333+
})
334+
.add('autosize', () => {
335+
const minRows = number('minRows', 0);
336+
const maxRows = number('maxRows', 0);
337+
const value = text('value', 'Hello world!');
338+
return {
339+
moduleMetadata: {
340+
imports: [FormsModule, InputModule],
341+
},
342+
template: /* HTML */ `<textarea
343+
[autosize]="{ minRows: minRows, maxRows: maxRows }"
344+
[(ngModel)]="value"
345+
></textarea>`,
346+
props: {
347+
minRows,
348+
maxRows,
349+
value,
350+
},
351+
};
344352
});

0 commit comments

Comments
 (0)
Please sign in to comment.