fix(textarea): sync rows property instead of delegating

This commit is contained in:
Thomas Allmer 2019-08-02 18:05:25 +02:00 committed by Joren Broekema
parent b3a1f912bc
commit 7ac9d88921
2 changed files with 43 additions and 26 deletions

View file

@ -1,7 +1,6 @@
import autosize from 'autosize/src/autosize.js';
import { LionInput } from '@lion/input';
import { css } from '@lion/core';
import { ObserverMixin } from '@lion/core/src/ObserverMixin.js';
/**
* LionTextarea: extension of lion-field with native input element in place and user friendly API
@ -9,30 +8,17 @@ import { ObserverMixin } from '@lion/core/src/ObserverMixin.js';
* @customElement
* @extends LionInput
*/
export class LionTextarea extends ObserverMixin(LionInput) {
export class LionTextarea extends LionInput {
static get properties() {
return {
maxRows: {
type: Number,
attribute: 'max-rows',
},
};
}
get delegations() {
return {
...super.delegations,
target: () => this.inputElement,
properties: [...super.delegations.properties, 'rows'],
attributes: [...super.delegations.attributes, 'rows'],
};
}
static get asyncObservers() {
return {
...super.asyncObservers,
resizeTextarea: ['maxRows', 'modelValue'],
setTextareaMaxHeight: ['maxRows', 'rows'],
rows: {
type: Number,
reflect: true,
},
};
}
@ -68,6 +54,24 @@ export class LionTextarea extends ObserverMixin(LionInput) {
autosize.destroy(this.inputElement);
}
updated(changedProperties) {
super.updated(changedProperties);
if (changedProperties.has('rows')) {
const native = this.inputElement;
if (native) {
native.rows = this.rows;
}
}
if (changedProperties.has('modelValue')) {
this.resizeTextarea();
}
if (changedProperties.has('maxRows') || changedProperties.has('rows')) {
this.setTextareaMaxHeight();
}
}
/**
* To support maxRows we need to set max-height of the textarea
*/

View file

@ -16,12 +16,28 @@ describe('<lion-textarea>', () => {
expect(el.querySelector('textarea').nodeName).to.equal('TEXTAREA');
});
it('has default minRows and maxRows', async () => {
it('has .rows=2 and .maxRows=6', async () => {
const el = await fixture(`<lion-textarea></lion-textarea>`);
expect(el.rows).to.equal(2);
expect(el.maxRows).to.equal(6);
});
it('has .rows=2 and rows="2" by default', async () => {
const el = await fixture(`<lion-textarea>foo</lion-textarea>`);
expect(el.rows).to.equal(2);
expect(el.getAttribute('rows')).to.be.equal('2');
expect(el.inputElement.rows).to.equal(2);
expect(el.inputElement.getAttribute('rows')).to.be.equal('2');
});
it('sync rows down to the native textarea', async () => {
const el = await fixture(`<lion-textarea rows="8">foo</lion-textarea>`);
expect(el.rows).to.equal(8);
expect(el.getAttribute('rows')).to.be.equal('8');
expect(el.inputElement.rows).to.equal(8);
expect(el.inputElement.getAttribute('rows')).to.be.equal('8');
});
it('disables user resize behavior', async () => {
if (!hasBrowserResizeSupport()) {
return;
@ -102,12 +118,9 @@ describe('<lion-textarea>', () => {
});
it('stops shrinking after property "rows" is reached', async () => {
const el = await fixture(
html`
<lion-textarea rows="1" max-rows="3"></lion-textarea>
`,
);
const el = await fixture(html`
<lion-textarea rows="1" max-rows="3"></lion-textarea>
`);
expect(el.scrollHeight).to.be.equal(el.clientHeight);
const oneRowHeight = el.clientHeight;