fix(input-tel(-dropdown)): align with SlotMixin rerender functionality

This commit is contained in:
Thijs Louisse 2022-11-16 19:41:07 +01:00 committed by Thomas Allmer
parent bc2527030b
commit ae06eb01f3
3 changed files with 30 additions and 41 deletions

View file

@ -1,4 +1,4 @@
import { html, render, css } from 'lit';
import { html, css } from 'lit';
import { ref, createRef } from 'lit/directives/ref.js';
import { LionInputTel } from '@lion/ui/input-tel.js';
@ -99,6 +99,7 @@ export class LionInputTelDropdown extends LionInputTel {
},
},
};
return {
refs,
data: {
@ -155,7 +156,7 @@ export class LionInputTelDropdown extends LionInputTel {
css`
/**
* We need to align the height of the dropdown with the height of the text field.
* We target the HTMLDivElement 'this.__dropdownRenderParent' here. Its child,
* We target the HTMLDivElement (render wrapper from SlotMixin) here. Its child,
* [data-ref=dropdown], recieves a 100% height as well via inline styles (since we
* can't target from shadow styles).
*/
@ -171,7 +172,19 @@ export class LionInputTelDropdown extends LionInputTel {
get slots() {
return {
...super.slots,
prefix: () => this.__dropdownRenderParent,
prefix: () => {
const ctor = /** @type {typeof LionInputTelDropdown} */ (this.constructor);
// If the user locally overrode the templates, get those on the instance
// @ts-expect-error
const templates = this.templates || ctor.templates;
return {
template: templates.dropdown(this._templateDataDropdown),
afterRender: () => {
this.__syncRegionWithDropdown();
},
};
},
};
}
@ -186,7 +199,6 @@ export class LionInputTelDropdown extends LionInputTel {
type: 'region',
});
this.__createRegionMeta();
this._scheduleLightDomRender();
}
/**
@ -195,6 +207,8 @@ export class LionInputTelDropdown extends LionInputTel {
_onPhoneNumberUtilReady() {
super._onPhoneNumberUtilReady();
this.__createRegionMeta();
// render dropdown (trigger render of prefix slot via SlotMixin)
this.requestUpdate();
}
/**
@ -219,9 +233,6 @@ export class LionInputTelDropdown extends LionInputTel {
*/
this._preferredCountriesLabel = '';
/** @type {HTMLDivElement} */
this.__dropdownRenderParent = document.createElement('div');
/**
* Contains everything needed for rendering region options:
* region code, country code, display name according to locale, display name
@ -259,9 +270,9 @@ export class LionInputTelDropdown extends LionInputTel {
updated(changedProperties) {
super.updated(changedProperties);
if (changedProperties.has('_needsLightDomRender')) {
this.__renderDropdown();
}
// if (changedProperties.has('_needsLightDomRender')) {
// this.__renderDropdown();
// }
if (changedProperties.has('activeRegion')) {
this.__syncRegionWithDropdown();
}
@ -326,6 +337,7 @@ export class LionInputTelDropdown extends LionInputTel {
if (prevActiveRegion !== this.activeRegion && !this.focused && this._phoneUtil) {
const prevCountryCode = this._phoneUtil.getCountryCodeForRegionCode(prevActiveRegion);
const countryCode = this._phoneUtil.getCountryCodeForRegionCode(this.activeRegion);
if (this.value.includes(`+${prevCountryCode}`)) {
this.modelValue = this._callParser(
this.value.replace(`+${prevCountryCode}`, `+${countryCode}`),
@ -350,25 +362,6 @@ export class LionInputTelDropdown extends LionInputTel {
}
}
/**
* Abstract away rendering to light dom, so that we can rerender when needed
* @private
*/
__renderDropdown() {
const ctor = /** @type {typeof LionInputTelDropdown} */ (this.constructor);
// If the user locally overrode the templates, get those on the instance
const templates = this.templates || ctor.templates;
render(
templates.dropdown(this._templateDataDropdown),
this.__dropdownRenderParent,
/** @type {RenderOptions} */ ({
scopeName: this.localName,
eventContext: this,
}),
);
this.__syncRegionWithDropdown();
}
/**
* @private
*/
@ -411,6 +404,7 @@ export class LionInputTelDropdown extends LionInputTel {
if (!this._allowedOrAllRegions?.length || !this.__namesForLocale) {
return;
}
this.__regionMetaList = [];
this.__regionMetaListPreferred = [];
this._allowedOrAllRegions.forEach(regionCode => {

View file

@ -71,6 +71,7 @@ export function runInputTelDropdownSuite({ klass } = { klass: LionInputTelDropdo
it('syncs value of dropdown on init if input has no value', async () => {
const el = await fixture(html` <${tag}></${tag}> `);
// await el.updateComplete;
expect(el.activeRegion).to.equal('GB');
expect(el.value).to.equal('+44');
expect(getDropdownValue(/** @type {DropdownElement} */ (el.refs.dropdown.value))).to.equal(
@ -92,7 +93,7 @@ export function runInputTelDropdownSuite({ klass } = { klass: LionInputTelDropdo
it('syncs value of dropdown on init if input has no value does not influence interaction states', async () => {
const el = await fixture(html` <${tag}></${tag}> `);
// TODO find out why its get dirty again
// expect(el.dirty).to.be.false;
expect(el.dirty).to.be.false;
expect(el.prefilled).to.be.false;
});
@ -245,10 +246,10 @@ export function runInputTelDropdownSuite({ klass } = { klass: LionInputTelDropdo
const { resolveLoaded } = mockPhoneUtilManager();
const el = await fixture(html` <${tag} .allowedRegions="${['DE']}"></${tag}> `);
// @ts-ignore
const spy = sinon.spy(el, '_scheduleLightDomRender');
const spy = sinon.spy(el, '__rerenderSlot');
resolveLoaded(undefined);
await aTimeout(0);
expect(spy).to.have.been.calledOnce;
expect(spy).to.have.been.calledWith('prefix');
restorePhoneUtilManager();
spy.restore();
});
@ -323,6 +324,7 @@ export function runInputTelDropdownSuite({ klass } = { klass: LionInputTelDropdo
mimicUserChangingDropdown(el.refs.dropdown.value, 'BE');
await el.updateComplete;
await el.updateComplete;
expect(el.value).to.equal('+32 612345678');
});

View file

@ -305,20 +305,13 @@ export class LionInputTel extends LocalizeMixin(LionInput) {
// This should trigger a rerender in shadow dom
this._phoneUtil = /** @type {AwesomePhoneNumber} */ (PhoneUtilManager.PhoneUtil);
// This should trigger a rerender in light dom
this._scheduleLightDomRender();
// this._scheduleLightDomRender();
// this._scheduleSlotRenderFor('prefix');
// Format when libPhoneNumber is loaded
this._calculateValues({ source: null });
this.__calculateActiveRegion();
}
/**
* This allows to hook into the update hook
* @protected
*/
_scheduleLightDomRender() {
this._needsLightDomRender += 1;
}
/**
* @private
*/