Merge pull request #1459 from ing-bank/input-amount-locale

Input amount locale
This commit is contained in:
gerjanvangeest 2021-07-19 16:08:25 +02:00 committed by GitHub
commit 2abb04cddd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 111 additions and 30 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/input-amount': patch
---
Reformat input-amount's formattedValue on locale changes, also respond to locale property.

View file

@ -0,0 +1,5 @@
---
'@lion/localize': patch
---
Fix onLocaleChanged method missing param types

View file

@ -35,14 +35,16 @@ export const currencySuffix = () => html`
Locale can be forced for a specific `lion-input-amount`. It will format the amount according to this locale. Locale can be forced for a specific `lion-input-amount`. It will format the amount according to this locale.
```js preview-story ```js preview-story
export const forceLocale = () => html` export const forceLocale = () => {
<lion-input-amount return html`
label="Price" <lion-input-amount
currency="JOD" label="Price"
.formatOptions=${{ locale: 'nl-NL' }} currency="JOD"
.modelValue=${123456.78} .locale="nl-NL"
></lion-input-amount> .modelValue=${123456.78}
`; ></lion-input-amount>
`;
};
``` ```
> The separators are now flipped due to Dutch locale. On top of that, due to JOD currency, the minimum amount of decimals is 3 by default for this currency. > The separators are now flipped due to Dutch locale. On top of that, due to JOD currency, the minimum amount of decimals is 3 by default for this currency.

View file

@ -26,6 +26,7 @@ export class LionInputAmount extends LocalizeMixin(LionInput) {
* validators. * validators.
*/ */
modelValue: Number, modelValue: Number,
locale: { attribute: false },
}; };
} }
@ -68,6 +69,8 @@ export class LionInputAmount extends LocalizeMixin(LionInput) {
this.formatter = formatAmount; this.formatter = formatAmount;
/** @type {string | undefined} */ /** @type {string | undefined} */
this.currency = undefined; this.currency = undefined;
/** @type {string | undefined} */
this.locale = undefined;
this.defaultValidators.push(new IsNumber()); this.defaultValidators.push(new IsNumber());
} }
@ -88,6 +91,28 @@ export class LionInputAmount extends LocalizeMixin(LionInput) {
if (changedProperties.has('currency') && this.currency) { if (changedProperties.has('currency') && this.currency) {
this._onCurrencyChanged({ currency: this.currency }); this._onCurrencyChanged({ currency: this.currency });
} }
if (changedProperties.has('locale') && this.locale !== changedProperties.get('locale')) {
if (this.locale) {
this.formatOptions.locale = this.locale;
} else {
delete this.formatOptions.locale;
}
this.__reformat();
}
}
/**
* @param {string} newLocale
* @param {string} oldLocale
* @enhance LocalizeMixin
*/
onLocaleChanged(newLocale, oldLocale) {
super.onLocaleChanged(newLocale, oldLocale);
// If locale property is used, no need to respond to global locale changes
if (!this.locale) {
this.__reformat();
}
} }
/** /**
@ -126,4 +151,8 @@ export class LionInputAmount extends LocalizeMixin(LionInput) {
get __currencyLabel() { get __currencyLabel() {
return this.currency ? formatCurrencyLabel(this.currency, localize.locale) : ''; return this.currency ? formatCurrencyLabel(this.currency, localize.locale) : '';
} }
__reformat() {
this.formattedValue = this._callFormatter();
}
} }

View file

@ -70,6 +70,30 @@ describe('<lion-input-amount>', () => {
expect(el.formattedValue).to.equal('123,456.78'); // should stay British expect(el.formattedValue).to.equal('123,456.78'); // should stay British
}); });
it('reformats the formattedValue when locale property changes', async () => {
const el = /** @type {LionInputAmount} */ (
await fixture(html`
<lion-input-amount .modelValue=${123456.78} .locale="${'en-GB'}"></lion-input-amount>
`)
);
expect(el.formattedValue).to.equal('123,456.78');
el.locale = 'nl-NL';
await el.updateComplete;
expect(el.formattedValue).to.equal('123.456,78');
});
it('reformats the formattedValue with global locale if locale property is unset', async () => {
const el = /** @type {LionInputAmount} */ (
await fixture(html`
<lion-input-amount .modelValue=${123456.78} .locale="${'nl-NL'}"></lion-input-amount>
`)
);
expect(el.formattedValue).to.equal('123.456,78');
el.locale = '';
await el.updateComplete;
expect(el.formattedValue).to.equal('123,456.78');
});
it('uses parseAmount for parsing', async () => { it('uses parseAmount for parsing', async () => {
const el = /** @type {LionInputAmount} */ ( const el = /** @type {LionInputAmount} */ (
await fixture(`<lion-input-amount></lion-input-amount>`) await fixture(`<lion-input-amount></lion-input-amount>`)
@ -157,7 +181,44 @@ describe('<lion-input-amount>', () => {
).to.equal('my-currency'); ).to.equal('my-currency');
}); });
it('reformats on locale changes', async () => {
const el = /** @type {LionInputAmount} */ (
await fixture(
html`<lion-input-amount
label="Price"
currency="EUR"
.modelValue=${123.45}
></lion-input-amount>`,
)
);
expect(el.formattedValue).to.equal('123.45');
localize.locale = 'nl-NL';
await el.updateComplete;
expect(el.formattedValue).to.equal('123,45');
});
describe('Accessibility', () => { describe('Accessibility', () => {
it('is accessible', async () => {
const el = await fixture(
`<lion-input-amount><label slot="label">Label</label></lion-input-amount>`,
);
await expect(el).to.be.accessible();
});
it('is accessible when readonly', async () => {
const el = await fixture(
`<lion-input-amount readonly .modelValue=${'123'}><label slot="label">Label</label></lion-input-amount>`,
);
await expect(el).to.be.accessible();
});
it('is accessible when disabled', async () => {
const el = await fixture(
`<lion-input-amount disabled><label slot="label">Label</label></lion-input-amount>`,
);
await expect(el).to.be.accessible();
});
it('adds currency id to aria-labelledby of input', async () => { it('adds currency id to aria-labelledby of input', async () => {
const el = /** @type {LionInputAmount} */ ( const el = /** @type {LionInputAmount} */ (
await fixture(`<lion-input-amount currency="EUR"></lion-input-amount>`) await fixture(`<lion-input-amount currency="EUR"></lion-input-amount>`)
@ -182,25 +243,4 @@ describe('<lion-input-amount>', () => {
// expect(el._currencyDisplayNode?.getAttribute('aria-label')).to.equal('Philippine pisos'); // expect(el._currencyDisplayNode?.getAttribute('aria-label')).to.equal('Philippine pisos');
}); });
}); });
it('is accessible', async () => {
const el = await fixture(
`<lion-input-amount><label slot="label">Label</label></lion-input-amount>`,
);
await expect(el).to.be.accessible();
});
it('is accessible when readonly', async () => {
const el = await fixture(
`<lion-input-amount readonly .modelValue=${'123'}><label slot="label">Label</label></lion-input-amount>`,
);
await expect(el).to.be.accessible();
});
it('is accessible when disabled', async () => {
const el = await fixture(
`<lion-input-amount disabled><label slot="label">Label</label></lion-input-amount>`,
);
await expect(el).to.be.accessible();
});
}); });

View file

@ -68,7 +68,7 @@ declare class LocalizeMixinHost {
public performUpdate(): Promise<void>; public performUpdate(): Promise<void>;
public onLocaleReady(): void; public onLocaleReady(): void;
public onLocaleChanged(): void; public onLocaleChanged(newLocale: string, oldLocale: string): void;
public onLocaleUpdated(): void; public onLocaleUpdated(): void;
public connectedCallback(): void; public connectedCallback(): void;
public disconnectedCallback(): void; public disconnectedCallback(): void;