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 { expect, fixture } from '@open-wc/testing';
|
||||
import { html } from 'lit/static-html.js';
|
||||
import { PhoneUtilManager } from '@lion/input-tel';
|
||||
import { getAllTagNames } from './helpers/helpers.js';
|
||||
import './helpers/umbrella-form.js';
|
||||
|
||||
/**
|
||||
* @typedef {import('./helpers/umbrella-form.js').UmbrellaForm} UmbrellaForm
|
||||
* @typedef {import('@lion/input-tel-dropdown').LionInputTelDropdown} LionInputTelDropdown
|
||||
*/
|
||||
|
||||
// Test umbrella form.
|
||||
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 () => {
|
||||
const el = /** @type {UmbrellaForm} */ (await fixture(html`<umbrella-form></umbrella-form>`));
|
||||
await el.updateComplete;
|
||||
|
|
@ -43,6 +50,10 @@ describe('Form Integrations', () => {
|
|||
const el = /** @type {UmbrellaForm} */ (await fixture(html`<umbrella-form></umbrella-form>`));
|
||||
await el.updateComplete;
|
||||
const formEl = el._lionFormNode;
|
||||
const inputTelDropdownEl = /** @type {LionInputTelDropdown} */ (
|
||||
formEl.querySelector('lion-input-tel-dropdown')
|
||||
);
|
||||
await inputTelDropdownEl?.updateComplete;
|
||||
|
||||
expect(formEl.formattedValue).to.eql({
|
||||
full_name: { first_name: '', last_name: '' },
|
||||
|
|
@ -63,7 +74,7 @@ describe('Form Integrations', () => {
|
|||
notifications: '',
|
||||
rsvp: '',
|
||||
tel: '',
|
||||
'tel-dropdown': '',
|
||||
'tel-dropdown': '+44',
|
||||
comments: '',
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -279,6 +279,33 @@ export class LionInputTelDropdown extends LionInputTel {
|
|||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
const prevActiveRegion = this.activeRegion;
|
||||
this._setActiveRegion(
|
||||
/** @type {RegionCode} */ (event.target.value || event.target.modelValue),
|
||||
);
|
||||
this._setActiveRegion(dropdownValue);
|
||||
|
||||
// Change region code in text box
|
||||
// From: https://bl00mber.github.io/react-phone-input-2.html
|
||||
if (prevActiveRegion !== this.activeRegion && !this.focused && this._phoneUtil) {
|
||||
const prevCountryCode = this._phoneUtil.getCountryCodeForRegionCode(prevActiveRegion);
|
||||
const countryCode = this._phoneUtil.getCountryCodeForRegionCode(this.activeRegion);
|
||||
if (countryCode && !this.modelValue) {
|
||||
// When textbox is empty, prefill it with country code
|
||||
this.modelValue = `+${countryCode}`;
|
||||
} else if (prevCountryCode && countryCode) {
|
||||
// When textbox is not empty, replace country code
|
||||
this.modelValue = this._callParser(
|
||||
this.value.replace(`+${prevCountryCode}`, `+${countryCode}`),
|
||||
);
|
||||
}
|
||||
this.modelValue = this._callParser(
|
||||
this.value.replace(`+${prevCountryCode}`, `+${countryCode}`),
|
||||
);
|
||||
}
|
||||
|
||||
// Put focus on text box
|
||||
|
|
|
|||
|
|
@ -71,6 +71,53 @@ export function runInputTelDropdownSuite({ klass } = { klass: LionInputTelDropdo
|
|||
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', () => {
|
||||
it('calls `templates.dropdown` with TemplateDataForDropdownInputTel object', async () => {
|
||||
const el = fixtureSync(html` <${tag}
|
||||
|
|
@ -261,7 +308,9 @@ export function runInputTelDropdownSuite({ klass } = { klass: LionInputTelDropdo
|
|||
});
|
||||
|
||||
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
|
||||
mimicUserChangingDropdown(el.refs.dropdown.value, 'BE');
|
||||
await el.updateComplete;
|
||||
|
|
|
|||
Loading…
Reference in a new issue