fix(input-tel-dropdown): syncs value of dropdown on init if input has no value
Co-authored-by: Thijs Louisse <thijs.louisse@ing.com>
This commit is contained in:
parent
362ee0e2e9
commit
9591732f4e
4 changed files with 101 additions and 15 deletions
5
.changeset/real-actors-drum.md
Normal file
5
.changeset/real-actors-drum.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@lion/input-tel-dropdown': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Syncs value of dropdown on init if input has no value
|
||||||
|
|
@ -1,15 +1,22 @@
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import { expect, fixture } from '@open-wc/testing';
|
import { expect, fixture } from '@open-wc/testing';
|
||||||
import { html } from 'lit/static-html.js';
|
import { html } from 'lit/static-html.js';
|
||||||
|
import { PhoneUtilManager } from '@lion/input-tel';
|
||||||
import { getAllTagNames } from './helpers/helpers.js';
|
import { getAllTagNames } from './helpers/helpers.js';
|
||||||
import './helpers/umbrella-form.js';
|
import './helpers/umbrella-form.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('./helpers/umbrella-form.js').UmbrellaForm} UmbrellaForm
|
* @typedef {import('./helpers/umbrella-form.js').UmbrellaForm} UmbrellaForm
|
||||||
|
* @typedef {import('@lion/input-tel-dropdown').LionInputTelDropdown} LionInputTelDropdown
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Test umbrella form.
|
// Test umbrella form.
|
||||||
describe('Form Integrations', () => {
|
describe('Form Integrations', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
// Wait till PhoneUtilManager has been loaded
|
||||||
|
await PhoneUtilManager.loadComplete;
|
||||||
|
});
|
||||||
|
|
||||||
it('".serializedValue" returns all non disabled fields based on form structure', async () => {
|
it('".serializedValue" returns all non disabled fields based on form structure', async () => {
|
||||||
const el = /** @type {UmbrellaForm} */ (await fixture(html`<umbrella-form></umbrella-form>`));
|
const el = /** @type {UmbrellaForm} */ (await fixture(html`<umbrella-form></umbrella-form>`));
|
||||||
await el.updateComplete;
|
await el.updateComplete;
|
||||||
|
|
@ -43,6 +50,10 @@ describe('Form Integrations', () => {
|
||||||
const el = /** @type {UmbrellaForm} */ (await fixture(html`<umbrella-form></umbrella-form>`));
|
const el = /** @type {UmbrellaForm} */ (await fixture(html`<umbrella-form></umbrella-form>`));
|
||||||
await el.updateComplete;
|
await el.updateComplete;
|
||||||
const formEl = el._lionFormNode;
|
const formEl = el._lionFormNode;
|
||||||
|
const inputTelDropdownEl = /** @type {LionInputTelDropdown} */ (
|
||||||
|
formEl.querySelector('lion-input-tel-dropdown')
|
||||||
|
);
|
||||||
|
await inputTelDropdownEl?.updateComplete;
|
||||||
|
|
||||||
expect(formEl.formattedValue).to.eql({
|
expect(formEl.formattedValue).to.eql({
|
||||||
full_name: { first_name: '', last_name: '' },
|
full_name: { first_name: '', last_name: '' },
|
||||||
|
|
@ -63,7 +74,7 @@ describe('Form Integrations', () => {
|
||||||
notifications: '',
|
notifications: '',
|
||||||
rsvp: '',
|
rsvp: '',
|
||||||
tel: '',
|
tel: '',
|
||||||
'tel-dropdown': '',
|
'tel-dropdown': '+44',
|
||||||
comments: '',
|
comments: '',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,33 @@ export class LionInputTelDropdown extends LionInputTel {
|
||||||
this.refs.dropdown?.value?.removeAttribute('disabled');
|
this.refs.dropdown?.value?.removeAttribute('disabled');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (changedProperties.has('_phoneUtil')) {
|
||||||
|
this._initModelValueBasedOnDropdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_initModelValueBasedOnDropdown() {
|
||||||
|
if (!this._initialModelValue && !this.dirty && this._phoneUtil) {
|
||||||
|
const countryCode = this._phoneUtil.getCountryCodeForRegionCode(this.activeRegion);
|
||||||
|
this.__initializedRegionCode = `+${countryCode}`;
|
||||||
|
this.modelValue = this.__initializedRegionCode;
|
||||||
|
this._initialModelValue = this.__initializedRegionCode;
|
||||||
|
this.initInteractionState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for Required validation and computation of interaction states.
|
||||||
|
* We need to override this, because we prefill the input with the region code (like +31), but for proper UX,
|
||||||
|
* we don't consider this as having interaction state `prefilled`
|
||||||
|
* @param {string} modelValue
|
||||||
|
* @return {boolean}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_isEmpty(modelValue = this.modelValue) {
|
||||||
|
// the activeRegion is not synced on time, so it can't be used in this check
|
||||||
|
return super._isEmpty(modelValue) || this.value === this.__initializedRegionCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -287,29 +314,23 @@ export class LionInputTelDropdown extends LionInputTel {
|
||||||
*/
|
*/
|
||||||
_onDropdownValueChange(event) {
|
_onDropdownValueChange(event) {
|
||||||
const isInitializing = event.detail?.initialize || !this._phoneUtil;
|
const isInitializing = event.detail?.initialize || !this._phoneUtil;
|
||||||
if (isInitializing) {
|
const dropdownValue = /** @type {RegionCode} */ (event.target.modelValue || event.target.value);
|
||||||
|
|
||||||
|
if (isInitializing || (this.activeRegion && this.activeRegion === dropdownValue)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const prevActiveRegion = this.activeRegion;
|
const prevActiveRegion = this.activeRegion;
|
||||||
this._setActiveRegion(
|
this._setActiveRegion(dropdownValue);
|
||||||
/** @type {RegionCode} */ (event.target.value || event.target.modelValue),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Change region code in text box
|
// Change region code in text box
|
||||||
// From: https://bl00mber.github.io/react-phone-input-2.html
|
// From: https://bl00mber.github.io/react-phone-input-2.html
|
||||||
if (prevActiveRegion !== this.activeRegion && !this.focused && this._phoneUtil) {
|
if (prevActiveRegion !== this.activeRegion && !this.focused && this._phoneUtil) {
|
||||||
const prevCountryCode = this._phoneUtil.getCountryCodeForRegionCode(prevActiveRegion);
|
const prevCountryCode = this._phoneUtil.getCountryCodeForRegionCode(prevActiveRegion);
|
||||||
const countryCode = this._phoneUtil.getCountryCodeForRegionCode(this.activeRegion);
|
const countryCode = this._phoneUtil.getCountryCodeForRegionCode(this.activeRegion);
|
||||||
if (countryCode && !this.modelValue) {
|
this.modelValue = this._callParser(
|
||||||
// When textbox is empty, prefill it with country code
|
this.value.replace(`+${prevCountryCode}`, `+${countryCode}`),
|
||||||
this.modelValue = `+${countryCode}`;
|
);
|
||||||
} else if (prevCountryCode && countryCode) {
|
|
||||||
// When textbox is not empty, replace country code
|
|
||||||
this.modelValue = this._callParser(
|
|
||||||
this.value.replace(`+${prevCountryCode}`, `+${countryCode}`),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put focus on text box
|
// Put focus on text box
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,53 @@ export function runInputTelDropdownSuite({ klass } = { klass: LionInputTelDropdo
|
||||||
await PhoneUtilManager.loadComplete;
|
await PhoneUtilManager.loadComplete;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('syncs value of dropdown on init if input has no value', async () => {
|
||||||
|
const el = await fixture(html` <${tag}></${tag}> `);
|
||||||
|
expect(el.activeRegion).to.equal('GB');
|
||||||
|
expect(el.value).to.equal('+44');
|
||||||
|
expect(getDropdownValue(/** @type {DropdownElement} */ (el.refs.dropdown.value))).to.equal(
|
||||||
|
'GB',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('syncs value of dropdown on reset if input has no value', async () => {
|
||||||
|
const el = await fixture(html` <${tag}></${tag}> `);
|
||||||
|
el.modelValue = '+31612345678';
|
||||||
|
await el.updateComplete;
|
||||||
|
expect(el.activeRegion).to.equal('NL');
|
||||||
|
el.reset();
|
||||||
|
await el.updateComplete;
|
||||||
|
expect(el.activeRegion).to.equal('GB');
|
||||||
|
expect(el.value).to.equal('+44');
|
||||||
|
});
|
||||||
|
|
||||||
|
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.prefilled).to.be.false;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('syncs value of dropdown on reset also resets interaction states', async () => {
|
||||||
|
const el = await fixture(html` <${tag}></${tag}> `);
|
||||||
|
el.modelValue = '+31612345678';
|
||||||
|
await el.updateComplete;
|
||||||
|
|
||||||
|
expect(el.dirty).to.be.true;
|
||||||
|
expect(el.prefilled).to.be.false;
|
||||||
|
el.reset();
|
||||||
|
await el.updateComplete;
|
||||||
|
expect(el.dirty).to.be.false;
|
||||||
|
expect(el.prefilled).to.be.false;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets correct interaction states on init if input has a value', async () => {
|
||||||
|
const el = await fixture(html` <${tag} .modelValue="${'+31612345678'}"></${tag}> `);
|
||||||
|
// TODO find out why its get dirty again
|
||||||
|
// expect(el.dirty).to.be.false;
|
||||||
|
expect(el.prefilled).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
describe('Dropdown display', () => {
|
describe('Dropdown display', () => {
|
||||||
it('calls `templates.dropdown` with TemplateDataForDropdownInputTel object', async () => {
|
it('calls `templates.dropdown` with TemplateDataForDropdownInputTel object', async () => {
|
||||||
const el = fixtureSync(html` <${tag}
|
const el = fixtureSync(html` <${tag}
|
||||||
|
|
@ -261,7 +308,9 @@ export function runInputTelDropdownSuite({ klass } = { klass: LionInputTelDropdo
|
||||||
});
|
});
|
||||||
|
|
||||||
it('prefills country code when textbox is empty', async () => {
|
it('prefills country code when textbox is empty', async () => {
|
||||||
const el = await fixture(html` <${tag} .allowedRegions="${['NL', 'BE']}"></${tag}> `);
|
const el = await fixture(
|
||||||
|
html` <${tag} .allowedRegions="${['NL', 'BE']}" .modelValue="${''}"></${tag}> `,
|
||||||
|
);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
mimicUserChangingDropdown(el.refs.dropdown.value, 'BE');
|
mimicUserChangingDropdown(el.refs.dropdown.value, 'BE');
|
||||||
await el.updateComplete;
|
await el.updateComplete;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue