ing-bank / lion Goto Github PK
View Code? Open in Web Editor NEWFundamental white label web component features for your design system.
Home Page: https://lion-web.netlify.app/
License: MIT License
Fundamental white label web component features for your design system.
Home Page: https://lion-web.netlify.app/
License: MIT License
As per my knowledge about the libraries. It provides Commonjs
, es
and umd
modules as output to consumed by projects. I don't see these modules in lion
. The source files being scattered in root directory which npm install lion
provides to consume. These modules are useful because it would be tested compiled and compressed. The Commonjs
and es
modules doesn't have any impact if the project uses any build script and does all building task. But umd
modules gives ability to use the library through the browser and check any components without a build script. This is very useful when you want to show the example through plunker
or stackblitz
.
I would like to configure the build script and would also like to organise the code for components being scatted at root level.
It's often unclear for people how the 'value computation loop' works.
* [1] Application Developer sets `.modelValue`:
* Flow: `.modelValue` -> `.formattedValue` -> `.inputElement.value`
* -> `.serializedValue`
* [2] End user interacts with field:
* Flow: `@user-input-changed` -> `.modelValue` -> `.formattedValue` - (debounce till reflect condition (formatOn) is met) -> `.inputElement.value`
* -> `.serializedValue`
lion-button
includes non-technical styling by default. This styling needs to then be overwritten by any design system implementing the button. This seems wasteful.
The modelValue is designed to be the Single Source of Truth. That means it should be possible to import and exported stored 'user sessions' (serialized modelValues).
Unparseable
values as prepopulated valuesLocalize has a facility to override the locale used for localizing. However, it is not possible to trigger loading a namespace for a specific locale because it is always retrieved from the this
: https://github.com/ing-bank/lion/blob/master/packages/localize/src/LocalizeManager.js#L66
Steps to replicate:
lion-select
modelValue
is empty (using property) <lion-select .modelValue="${this.someProperty}">
modelValue
changes, the display in the lion-select
element doesn't display the value but when trying to use $0.modelValue
, there is a value.Vice versa, when I use value
instead of modelValue
like <lion-select .value="${this.someProperty}">
, the display is updated with the correct value BUT the modelValue
is empty preventing the form to be submitted.
As a workaround, I used <lion-select .value="${this.someProperty}" .modelValue="${this.someProperty}">
(improvement proposal for to be deprecated DelegateMixin)
Composition is a very common pattern for our UI components, especially since it is not possible to extend native elements.
Often we do want to (partly) keep the original api, and therefore we need the delegation pattern.
this.requestUpdate()
is never called for them. Currently, only integrates with ObserverMixin (which should be opt-in mixin)static get properties
aria-label
or id
breaks functionality (as an example, since those props/attrs should never be delegated in the first place)<lion-input name=“myField”></lion-input>
-> it’s horrible DX that querySelector(‘[name=“myField”]’) now gives back the delegation target.disabled
, all its interactive children should become as wellstatic get properties
)@event
jdsoc.DelegatesMixin._delegateEvent(‘target-event’, targetNodeKey)
. This will listen for the event on target, cancel it and retrigger it under the same name on the host(will keep same characteristics, but sets target to host, since that is what is expected by AD).DelegatesMixin._syncDelegationTarget(targetNodeKey)
(also scheduled events are synced)<field-listbox-dropdown>
, I want to disable all interactive elements (button and listbox) whenever my hosts becomes disabledWill we ever be able to resolve the FIXMEs? Would it maybe be an idea to autogenerate this switch statement as a prepublish script, so we keep the source code succinct and maintainable?
Originally posted by @tlouisse in #100 (comment)
The last link in README.md to forms is broken.
--> https://github.com/ing-bank/lion/blob/master/docs/forms.md
I assume the correct one is this --> https://github.com/ing-bank/lion/blob/master/packages/field/docs/FormFundaments.md
Using @lion/core
in new projects on Stackblitz is not working anymore. Here is a fork of a project posted 8 days ago in one of the other issues: https://stackblitz.com/edit/lion-form-9r5wtq The only thing I changed is reinstalling the dependencies. Now, the app doesn't seem to be running anymore.
When looking in the sources of the example we see files of 2 versions of lit-html
being loaded (1.0.0 and 1.1.0):
After some investigation this is happening because of 3 separate things coming together:
@lion/core
is depending on a fixed version of lit-html
: 1.0.0
lit-element 2.1.0
is depending on lit-html: "^1.0.0"
, which is resolving to 1.1.0
since Tuesday (21/5), as a new version has been released.All of this affects the internal wiring of LitElement
, preventing the TemplateResult
to be rendered in the renderRoot
.
As lion is a library I think the best solution here is to have @lion/core
be dependent on ranges of lit-element
and lit-html
instead of fixed versions.
For some weird reason, in Edge (IE is fine) parent form elements don't seem to receive the form-element-register
event and thus doesn't register its child elements. When using derived fieldsets as radio-group
some of the methods and properties don't work as expected.
I have 3 that are dependent on each other. I have @change
event on my first element that will map and populate the options for the next select element. Once the property on the modelValue
and value
changes, @change
is not being triggered. It is only being triggered once I manually select an option.
LionButton
always sets a tabindex. It should not do this if the user already defined a tabindex himself.
https://github.com/ing-bank/lion/blob/master/packages/button/src/LionButton.js#L149
We need an alternative to <input pattern="...">
in our form system.
Having an lion-form
with one lion-input
marked as required, when this lion-input
stops being rendered the form shouldn't reflect an error state.
lion-form
can unregister inputs that stops being rendered in the form, so then the errorState
is correct when the form is submitted.
lion-form
doesn't unregister inputs that stops being rendered in the form, so then the errorState
doesn't reflect the real situation.
I have created a web component and a test for reproducing the bug, here the steps in the case that you want to test it manually:
1- Click Submit, errorState
should be true because the ing-input "name" is required.
2- Click in the button Toggle is name visible
3- The ing-input "name" is not rendered anymore
4- Click Submit, the errorState
should be false since there isn't any required input within the form
In the current situation the formatNumber displays the amount of 200.000 euro in Dutch:
I proposed this system already internally, moving it to github now.
The current icon system is a potential footgun for performance. I'd like to propose a change which improves performance and maintains a good developer experience.
In the current system the easiest way to use icons is by importing them synchronously. This method is also the default promoted/documented method. Sync imports will include the icons with the initial bundle of the application which for large applications can really add up to quite an amount.
Applications often have areas which are dynamic where it is not known beforehand what kind of content and icons will be shown. For example a user might be able to choose a profile picture from a set of icons, or the application might display a list of items where each item might have an icon based on some data from an API. In these case the list of possible icons is basically 'everything', resulting in all icons having to be imported and increasing the bundle size.
It is possible to use dynamic imports to load the icons, but this requires quite some extra boilerplate and specific knowledge. Also different teams might work on different areas of the application, and end up rewriting the same dynamic loading logic for the same icons.
Because lazy loading is not the default promoted and documented method most people will end up with the synchronous icon system anyway and (hopefully) only later find out that they need to refactor this to improve performance.
I propose a system similar to the localization system, and similar to the way iron-icon works. Developers use the icon element and specify a specific icon-id
:
<lion-icon icon-id="lion:space:meteor"></lion-icon>
The icon id is made up of a specific set of parts: <namespace>:<collection>:<icon>
. For each namespace a loader is defined which then lazily loads the icons on demand. For example:
icons.addIconResolver('lion', async (collection, iconName) => {
switch (collection) {
case 'bugs':
return (await import('./icons/bugs-collection.js'))[iconName];
case 'space':
return (await import('./icons/space-collection.js'))[iconName];
default:
throw new Error(`Unknown collection: ${collection}`);
}
});
In the example above a space icon is requested, so the space collection is imported and the meteor icon is returned. When another space icon is requested, the space collection was already imported so it won't be loaded again. It's better to bundle a set of icons together and import it, instead of doing separate imports for each icon.
Benefits:
IntersectionObserver
I implemented this already in my own application, with an extension on lion-icon
, and it works very well for us.
This test currently fails in IE11
it('disabled does not override user provided tabindex', async () => {
const el = await fixture(`<lion-button tabindex="5" disabled>foo</lion-button>`);
expect(el.getAttribute('tabindex')).to.equal('-1');
el.disabled = false;
await el.updateComplete;
expect(el.getAttribute('tabindex')).to.equal('5');
});
When the SlotMixin was designed, we aimed for a template system agnostic solution.
Since we embraced lit-html, let’s leverage its power also in SlotMixin.
It would change this:
label: () => {
const label = document.createElement('label');
label.textContent = this.label;
return label;
},
'help-text': () => {
const helpText = document.createElement('div');
helpText.textContent = this.helpText;
return helpText;
},
to this:
label: () => html`<label>”${this.label}”</label>`,
'help-text': () => html`<div>”${this.helpText}”</div>`,
It’s more concise and readable.
It would also be more in line with our existing templates (considering the fact that the slots are part of the template and are defined outside the main render()
for accessibility reasons only.)
@daKmoR @bashmish since you were both involved in the creation of this mixin as well, do you think it would be a nice improvement?
Note: This issue is based on the Popper POC , but is also an issue for the old implementation
I would expect the tooltip/popup to change position when I change the placement property programmatically.
There is nothing that handles updates of this property currently, and I think we should implement that it changes the popper config and calls popper.update() (if im not mistaken) to update the position.
This will not only help our users, but allow us to make an attractive demo to show all positions and let the user use Storybook Knobs to change it to how they like :).
Lion Web Components are still in an early alpha stage; they should not be considered production ready yet.
The goal of our pilot phase is to gather feedback from a private group of users. Therefore, during this phase, we kindly ask you to:
Feel free to subscribe to this issue to be notified as soon as the Pilot Phase ends.
The lint:eclint script currently don't work on windows machines.
The find command and the $ only works in unix environments, so probably it can be simplified and ignore unwanted files in the editorconfig file.
I want all components to work with all locales for languages we have in ./translations/
, while at the same time support polymer-cli
for the ones we manually define in static get localizeNamespaces()
.
It is easier to illustrate my idea with the code.
Imagine we have ./translations/en.js
and such code:
static get localizeNamespaces() {
return [
{
'lion-component': locale => {
switch (locale) {
case 'en-GB':
case 'en':
return import('../translations/en.js');
default:
throw new Error(`Unknown locale: ${locale}`);
}
},
},
...super.localizeNamespaces,
];
}
Then this code will work for en-AU
and en-US
thanks to just one change and this feature of localize:
static get localizeNamespaces() {
return [
{
'lion-component': locale => {
switch (locale) {
case 'en-GB':
case 'en':
return import('../translations/en.js');
default:
return import('../translations/${locale}.js'); // changed
}
},
},
...super.localizeNamespaces,
];
}
This implies that fact that 2 requests will be needed for locales which don't have a file in ./translations/
, because this is how this feature works. But we knew that when we designed it and that was a trade-off, it is just weird we are not using it since then ourselves.
This forward compatibility is useful for people using native dynamic imports or/and webpack for bundling, because they can then use existing languages that we already support, e.g. English, for other countries. For example, most of changes like this for "en-PH" will not be needed for them, unless they also need to support polymer-cli
.
I would say the fact we are not forward compatible with modern standards is a bug.
When browsing md files through Github, relative links work correctly.
However, after publishing individual packages to npm, the relative links miss context.
Proposed solution: create a prepublish script that translates relative links to hardcoded Github links (for instance '../../README.md' becomes 'https://github.com/ing-bank/lion/tree/master/packages/field/README.md') .
Note: based on Popper POC where the API changes to 1 placementConfig object.
Currently, the only override the user of Lion can do is the placement (or previously called position), but we should allow the user to override the entire placementConfig. LocaloverlayController already allows this :).
Right now, for a user to create their own branded popup, they would have to extend lion-popup and override the entire connectedCallback method (and therefore, create duplicate code). The more friendly way, that would be enabled by this change, would be to set their own default placementConfig in the constructor. This would in turn allow their end users to override it using the following syntax <branded-popup .placementConfig=${myPlacementConfig}>
Should make sure of course that programmatically changing this config should also re-render it to reflect those changes for which I also made an issue #103
The polymer gestures modules prevents programmatic clicks on mobile browsers. This is due to the fact that their event detection mechanism doesn't correctly detect the click events.
There is an open issue Polymer/polymer#5289 but I don't know if it will be solved anytime soon.
The lion project doesn't officially have anything to do with polymer, but we use lion-web and polymer in hybrid applications.
Possible solutions I can think of:
window.Polymer.Gestures.resetMouseCanceller();
before calling .click()
;.click()
on is a child of ing-button
, so that the detection works properlyinput.dispatchEvent(new MouseEvent('click', { bubbles: false }))
instead of a clickAny other ideas?
Heyo,
Not sure this is something that can/should be fixed, but I just banged my head against it so I thought it was worth mentioning.
I'm converting an existing form using generic HTML tags into lion
.
I was using lots of self-closing tags :
<input
id="accessToken"
name="accessToken"
placeholder="accessToken">
converted it to :
<lion-input
label="Personal Access Token"
id="accessToken"
type="password"
name="accessToken"
placeholder="accessToken">
Nothing to be seen on my page.
I looked into imports and all, searching for a generic web-components related imports error, but the issue was simply that I was missing the closing tag </lion-input>
.
Consequence was that I got nested elements, breaking the page :).
Testing out the storybook with the NVDA screenreader I immediately notice that the buttons are read out twice (except for the button consisting only of an icon).
Inspecting the DOM, I notice that the lion-button
element is given role="button"
. However, they also contain <button>
children. These are given tabindex="-1"
, and indeed if I navigate by tab each button is only read out once. However since the button elements are not hidden from the a11y tree I can still navigate to them with the screenreader virtual cursor (in my case by pushing the down arrow button). The first button for example is announced as "Button default" in NVDA. Moving the virtual cursor down then announces "Button clickable".
Demo: https://js-mu9ixf.stackblitz.io (edit: https://stackblitz.com/edit/js-mu9ixf)
Affected browsers and screen readers:
Originally, the FieldCustomMixin
was created to be used in conjunction with 'specialized' fields (input-iban, input-amount, input-date etc.) having defaults for help-texts, labels etc.
In the Lion versions of the specialized inputs mentioned above we have no default help-texts/labels applied. Therefore, the FieldCustomMixin has more right of existence on more opinionated, extending layers (not in Lion repo).
Currently, its functionality contains only the disabling of help-texts. For maximum flexibility, on extending layers it should contain:
If we would decide however to keep this mixin, we should rename it to something like 'SpecializedFieldMixin', to avoid confusion with custom field wrappers like described here: https://github.com/ing-bank/lion/tree/master/packages/field
I added readonly
property in my lion-input-datepicker
, but I am still able to select a new date value.
<lion-input-datepicker label="Date" readonly></lion-input-datepicker>
One of the test for lion-calendar is failing because it depends on actual day but is compared to constant day.
Test name: is on day closest to today, if today (and surrounding dates) is/are disabled
AssertionError: expected 21 to equal 17
While building the datepicker, I encountered a few missing features/shortcomings in the Overlay System:
- auto a11y for invokers
The overlay system takes care of all accessibility, the only thing that it doesn't take care of is the attrs for global overlays (aria-haspop="dialog" and aria-expanded="false/true" (should be toggled programatically when global overlay is non-modal)
- hidesOnOutsideClick support for global overlays.
A modal overlay shouldn't be closeable, but a global overlay is not neccessarily a modal overlay and should thus support this feature like localOverlay does (example: material design datepicker).
- No horizontal centering of dialog
Currently, the global dialog opens to the left of the screen. I think the default should be horizontally centered?
- No vertical centering of dialog
Currently, it opens ‘below the end of the page’. That means there is no relation to invoker element. Think the default should be either a fixed number from top of window or always vertically centered
- Not closing on esc when clicking on backdrop -> focus on body
A modal dialog allows to click on backdrop and then body becomes the document.activeElement
.
- elementToFocusAfterHide -> doesn’t work
Didn't check thoroughly, but I think it's not working (not when provided as arg to show method, also not when provided as prop 'elementToFocusAfterHide' to config.)
- Smarter defaults: always need to add these to my own styling:
- Position: relative so that it is positioned above backdrop
- Background: white (Just like HTML body. You can override to transparent or other color if needed.)
- Shadow dom encapsulation by default
The only way to make content put in global overlay not leak styles, is to put it in the web component you created yourself.
Imagine this:
const myCtrl = overlays.add(
new ModalDialogController({
contentTemplate: () => html`<div class="overlay"><div class="overlay-heading">bla</div></div>`,
}),
);
Now this overlay should be aware of its context. If it should be used in an app that could be placed in whatever legacy context, it can easily conflict when generic names are used. (a legacy app with .overlay { background: yellow }
would cause inward leaking.
Something like this already happened to one of our consumers.
The current solution, always providing our own web component, requires a lot more boilerplate (it's a bit cumbersome if you want to provide an api for Subclassers in the input-datepicker component). Also, if you provide content projection inside your web component, you would be exposed to global scope again. I think providing one layer of encapsulation above this, would solve this problem.
Also, .global-overlays
can be encapsulated by a shadow root to make sure it will never conflict with anything defined outside of it (this is actually the real conflict we encountered, when it was called 'overlay' and clashed with a 3rd party lib).
I think shadow dom encapsulation should be the default with an opt-out (if you want to hook in to a globally defined style lib, only for compatibility with legacy apps).
- Styling not configurable
I want to be able to change the colour, opacity, animation of the backdrop. Also want to override vertical placement etc. Making the global-overlays a wc, would make this easier and in line with other 'style patchings' for Subclassers.
@LarsDenBakker, @bashmish, @jorenbroekema, @daKmoR:
Could you please give your thoughts about the above?
Some of them might be design considerations and I might miss something in my proposed solutions?
When I add a click
event listener on a parent element of a lion-button
, it should give me back the lion-button
as target
on the event.
See: https://stackblitz.com/edit/lion-button-delegation?file=index.html
I found out why there is a difference between how disabled and readonly buttons looks like
for disabled we have this style:
:host(.state-disabled) .input-group ::slotted(*) {
color: var(--disabled-text-color, #adadad);
}
not for readonly though
this is just a side-effect of course, there was no intention to make a different colour of the button, but it is a bug, because in both cases the button should look like disabled and in both cases we need consistent styles which we just don't define and face a strange inconsistent side effect
_Originally posted by @bashmish in #105 (comment)
On previous versions, I was able to use the <lion-input-date>
without a default value (.modelValue
), and leave it blank when submitting the form since it's optional.
Upon loading of the page that contains the form, if I try to submit the form (with empty date), the date input from the form data is identified as Unparseable
. If I try to input a valid date, then remove the value, upon submitting the form, it is then able to allow an empty date input.
Add an lion-input-date
element to a form.
Leave the input date empty
Submit the form
If you check the contents of the form data from the submit method, it contains a date property with Unparseable
as its value.
When you create a new <lion-icon>
element, the svg
property is initially undefined, and it renders nothing (blank space).
When I explicitly set the svg
property to the value undefined
(after it being set as something else) it renders the text "undefined"
instead of rendering blank space.
I expect the element to render nothing when I set the svg
property to undefined
.
Upon adding and removing .errorValidators = ['required']
dynamically on textarea, when submitting the form without any value on textarea, the form is being submitted. The errorState is false. But, when trying to put something and removing the value before submitting the form, the required validation and working as expected.
Some of the default messages that are used by the validators do not work very well in all contexts. If you have a long label name for an input that is required you might get something such as 'Fill Do you already have an account? in.' Naturally, that is not desirable.
Currently we work around this issue by providing a fixed message on the global scope (i.e. 'This field is required.'), but we would like to be able to override the message on a per-field basis, without wrapping the input element.
Tried to have a look at implementing this myself, but I cannot see a proper way of doing this. Took a reasonably quick look at the validator mixin and the localization mixin. Any suggestions?
I try to run all the tests on IE11 (bs_win10_ie_11), and i got something like this:
λ npm run test:bs
> @lion/root@ test:bs D:\dev\lab\lion
> karma start karma.bs.config.js --coverage
START:
18 06 2019 21:28:51.979:WARN [filelist]: Pattern "D:/dev/lab/lion/__snapshots__/**/*.md" does not match any file.
18 06 2019 21:28:53.547:INFO [karma-server]: Karma v4.1.0 server started at http://0.0.0.0:9876/
18 06 2019 21:28:53.548:INFO [launcher]: Launching browsers bs_win10_ie_11 with concurrency unlimited
18 06 2019 21:28:53.607:INFO [launcher]: Starting browser IE 11.0 (Windows 10) on BrowserStack
18 06 2019 21:29:00.208:INFO [launcher.browserstack]: IE 11.0 (Windows 10) session at https://automate.browserstack.com/builds/a48343450ca0f66a4f1ac1da96d4536c314fe859/sessions/69d851431e3a82dc9cc70a483c21ff536a188c53
18 06 2019 21:29:05.135:INFO [IE 11.0.0 (Windows 10.0.0)]: Connected on socket RDJX-pPfYMpMcPdXAAAA with id 79747197
Finished in 0.003 secs / 0 secs @ 21:29:07 GMT+0300 (Eastern European Summer Time)
SUMMARY:
√ 0 tests completed
=============================== Coverage summary ===============================
Statements : Unknown% ( 0/0 )
Branches : Unknown% ( 0/0 )
Functions : Unknown% ( 0/0 )
Lines : Unknown% ( 0/0 )
================================================================================
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! @lion/root@ test:bs: `karma start karma.bs.config.js --coverage`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the @lion/root@ test:bs script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
I think is a problem with browserstack, also i found this issue.
When writing tests on forms, interacting with various inputs is viable. While working with the input-datepicker I found these test utils very helpful and time saving: https://github.com/ing-bank/lion/blob/master/packages/input-datepicker/test/test-utils.js
Exporting the test-utils
Making the utils available for public usage would make testing some steps easier and time saving. Especially in this case, where one must understand which components play together, e.g. date input, calendar overlay, selecting days and months etc.
Since lit-element is the base of Lion webcomponents and since lit-element support (pretty nicely) typescript, it would be great to have definitions files shipped with lion too.
As a kickstart, here is the one I started creating:
declare module '@lion/ajax' {
import { AxiosRequestConfig, AxiosPromise, AxiosError } from 'axios';
namespace ajax {
export type Promise<T> = AxiosPromise<T>;
export type Configuration = AxiosRequestConfig;
export type Error = AxiosError;
export type Data = Record<string, unknown>;
export function get<T>(url: string, configuration?: AxiosRequestConfig): Promise<T>;
function del<T>(url: string, configuration?: AxiosRequestConfig): Promise<T>;
export { del as delete };
export function patch<T>(url: string, data: Data, configuration?: AxiosRequestConfig): Promise<T>;
export function post<T>(url: string, data: Data, configuration?: AxiosRequestConfig): Promise<T>;
export function put<T>(url: string, data: Data, configuration?: AxiosRequestConfig): Promise<T>;
}
}
declare module '@lion/core' {
export * from 'lit-element';
export * from 'lit-html/directives/if-defined';
}
declare module '@lion/localize' {
import { LitElement } from 'lit-element';
namespace localize {
export function loadNamespace(namespace: Record<string, (locale: string) => Promise<unknown>>): void;
export function addEventListener(eventName: 'localeChanged', callback: () => void): void;
export function msg(key: string, variables: Record<string, unknown>): string;
export let locale: string;
}
class LocalizeClassMixin extends LitElement {
public static waitForLocalizeNamespaces: boolean;
public static localizeNamespaces: (Record<string, (locale: string) => Promise<unknown>>)[];
public performUpdate(): Promise<unknown> | void;
public connectedCallback(): void;
public disconnectedCallback(): void
public msgLit(key: string, variables?: Record<string, unknown>, options?: Record<string, unknown>): void | string;
public onLocaleReady(): void;
public onLocaleChanged(): void;
public onLocaleUpdated(): void
}
export function LocalizeMixin(superClass: typeof LitElement): typeof LocalizeClassMixin;
}
Clicking reset button should empty the input elements
Invalid input is retained in value
propert. However, when you inspect the modelValue
, it is already cleared. Even if you manually delete the value, the element is putting it back.
Hi! Would be possible to support in lionfield, the attributes: pattern, min and max?
Thanks!
Currently there are no proper demos for:
Those are like the form core functionalities and should be demoed individually instead of being scattered across individual element demos.
Fields containing valid modelValues should be run through a formatter, whereas invalid modelValues should not.
Values switching from invalid to valid are not formatted (after this pull request is merged they are) and values switching from valid to invalid will be formatted (but should not).
The pr mentioned provides a temporary workaround, but a proper solution is needed.
Setting of modelValue triggers observers for:
Observers will be handled in above order. Since computation of formattedValue depends on 'errorState' (erroneous inputs should not be formatted), the formatter is handled with a not yet updated errorState.
Rewrite to a flow handling observers in this order: modelValue -> errorState(validation) -> formattedValue
.
Important: in the referenced pr, a situation where a value changes from valid to invalid will still lead to formatting when not required.
Since the flow above involves two mixins (FormatMixin and ValidateMixin) and ValidateMixin should have no knowledge about FormatMixin, think of a proper way to do this.
It might be as easy as changing the order of mixins applied within LionField: if the ValidateMixin runs before the FormatMixin, the errorState should be computed by the time the formatter runs.
Currently, this happens:
if (this.modelValue instanceof Unparseable) {
return this.modelValue.viewValue;
}
if (this.errorState) {
return this.inputElement ? this.value : undefined;
}
return this.formatter(this.modelValue, this.formatOptions);
}
https://github.com/ing-bank/lion/blob/master/packages/field/src/FormatMixin.js#L186
It should not return the current value of the inputElement and sync it back. Whenever the formattedValue returns undefined, it should be decided in the sync down step to leave inputElement.value as is
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.