Socket
Socket
Sign inDemoInstall

@lion/field

Package Overview
Dependencies
Maintainers
1
Versions
103
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lion/field - npm Package Compare versions

Comparing version 0.1.22 to 0.1.23

11

CHANGELOG.md

@@ -6,2 +6,13 @@ # Change Log

## [0.1.23](https://github.com/ing-bank/lion/compare/@lion/field@0.1.22...@lion/field@0.1.23) (2019-07-02)
### Bug Fixes
* **field:** format conditionally on user input only ([af8046c](https://github.com/ing-bank/lion/commit/af8046c))
## [0.1.22](https://github.com/ing-bank/lion/compare/@lion/field@0.1.21...@lion/field@0.1.22) (2019-06-27)

@@ -8,0 +19,0 @@

4

package.json
{
"name": "@lion/field",
"version": "0.1.22",
"version": "0.1.23",
"description": "Fields are the most fundamental building block of the Form System",

@@ -44,3 +44,3 @@ "author": "ing-bank",

},
"gitHead": "187d50b6bc14b5c9a2fec3e4908a242513257617"
"gitHead": "e2a1986630108e02ecbfbb742bab6df6d5dfd32e"
}

@@ -9,3 +9,12 @@ /* eslint-disable class-methods-use-this */

/**
* @polymerMixin
* @desc Designed to be applied on top of a LionField
*
* FormatMixin supports these two main flows:
* 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`
*
* @mixinFunction

@@ -30,3 +39,4 @@ */

* - For a date input: a String '20/01/1999' will be converted to new Date('1999/01/20')
* - For a number input: a formatted String '1.234,56' will be converted to a Number: 1234.56
* - For a number input: a formatted String '1.234,56' will be converted to a Number:
* 1234.56
*/

@@ -53,9 +63,9 @@ modelValue: {

* This value exists for maximal compatibility with the platform API.
* The serialized value can be an interface in context where data binding is not supported
* and a serialized string needs to be set.
* The serialized value can be an interface in context where data binding is not
* supported and a serialized string needs to be set.
*
* Examples:
* - For a date input, this would be the iso format of a date, e.g. '1999-01-20'.
* - For a number input this would be the String representation of a float ('1234.56' instead
* of 1234.56)
* - For a number input this would be the String representation of a float ('1234.56'
* instead of 1234.56)
*

@@ -145,11 +155,12 @@ * When no parser is available, the value is usually the same as the formattedValue

/**
* Responsible for storing all representations(modelValue, serializedValue, formattedValue and
* value) of the input value.
* Prevents infinite loops, so all value observers can be treated like they will only be called
* once, without indirectly calling other observers.
* (in fact, some are called twice, but the __preventRecursiveTrigger lock prevents the second
* call from having effect).
* Responsible for storing all representations(modelValue, serializedValue, formattedValue
* and value) of the input value.
* Prevents infinite loops, so all value observers can be treated like they will only be
* called once, without indirectly calling other observers.
* (in fact, some are called twice, but the __preventRecursiveTrigger lock prevents the
* second call from having effect).
*
* @param {string} source - the type of value that triggered this method. It should not be set
* again, so that its observer won't be triggered. Can be: 'model'|'formatted'|'serialized'.
* @param {string} source - the type of value that triggered this method. It should not be
* set again, so that its observer won't be triggered. Can be:
* 'model'|'formatted'|'serialized'.
*/

@@ -189,3 +200,15 @@ _calculateValues({ source } = {}) {

}
if (this.errorState) {
// - Why check for this.errorState?
// We only want to format values that are considered valid. For best UX,
// we only 'reward' valid inputs.
// - Why check for __isHandlingUserInput?
// Downwards sync is prevented whenever we are in a `@user-input-changed` flow.
// If we are in a 'imperatively set `.modelValue`' flow, we want to reflect back
// the value, no matter what.
// This means, whenever we are in errorState, we and modelValue is set
// imperatively, we DO want to format a value (it is the only way to get meaningful
// input into `.inputElement` with modelValue as input)
if (this.__isHandlingUserInput && this.errorState) {
return this.inputElement ? this.value : undefined;

@@ -239,7 +262,5 @@ }

// Downwards syncing should only happen for <lion-field>.value changes from 'above'
this.__preventDownwardsSync = true;
// This triggers _onModelValueChanged and connects user input to the
// parsing/formatting/serializing loop
this.modelValue = this.__callParser(this.value);
this.__preventDownwardsSync = false;
}

@@ -252,5 +273,5 @@

// Downwards syncing 'back and forth' prevents change event from being fired in IE.
// So only sync when the source of new <lion-field>.value change was not the 'input' event of
// inputElement
if (!this.__preventDownwardsSync) {
// So only sync when the source of new <lion-field>.value change was not the 'input' event
// of inputElement
if (!this.__isHandlingUserInput) {
// Text 'undefined' should not end up in <input>

@@ -276,5 +297,8 @@ this.value = typeof this.formattedValue !== 'undefined' ? this.formattedValue : '';

_onUserInputChanged() {
// Upwards syncing. Most properties are delegated right away, value is synced to <lion-field>,
// to be able to act on (imperatively set) value changes
// Upwards syncing. Most properties are delegated right away, value is synced to
// <lion-field>, to be able to act on (imperatively set) value changes
this.__isHandlingUserInput = true;
this._syncValueUpwards();
this.__isHandlingUserInput = false;
}

@@ -300,7 +324,7 @@

this.addEventListener('user-input-changed', this._onUserInputChanged);
// Connect the value found in <input> to the formatting/parsing/serializing loop as a fallback
// mechanism. Assume the user uses the value property of the <lion-field>(recommended api) as
// the api (this is a downwards sync).
// However, when no value is specified on <lion-field>, have support for sync of the real input
// to the <lion-field> (upwards sync).
// Connect the value found in <input> to the formatting/parsing/serializing loop as a
// fallback mechanism. Assume the user uses the value property of the
// <lion-field>(recommended api) as the api (this is a downwards sync).
// However, when no value is specified on <lion-field>, have support for sync of the real
// input to the <lion-field> (upwards sync).
if (typeof this.modelValue === 'undefined') {

@@ -307,0 +331,0 @@ this._syncValueUpwards();

@@ -160,2 +160,21 @@ import { expect, fixture, html, aTimeout, defineCE, unsafeStatic } from '@open-wc/testing';

it('reflects back .formattedValue immediately when .modelValue changed imperatively', async () => {
const el = await fixture(html`
<${elem} .formatter="${value => `foo: ${value}`}">
<input slot="input" />
</${elem}>
`);
// The FormatMixin can be used in conjunction with the ValidateMixin, in which case
// it can hold errorState (affecting the formatting)
el.errorState = true;
// users types value 'test'
mimicUserInput(el, 'test');
expect(el.inputElement.value).to.not.equal('foo: test');
// Now see the difference for an imperative change
el.modelValue = 'test2';
expect(el.inputElement.value).to.equal('foo: test2');
});
describe('parsers/formatters/serializers', () => {

@@ -210,3 +229,3 @@ it('should call the parser|formatter|serializer provided by user', async () => {

it('will only call the formatter for valid values', async () => {
it('will only call the formatter for valid values on `user-input-changed` ', async () => {
const formatterSpy = sinon.spy(value => `foo: ${value}`);

@@ -221,8 +240,8 @@ const el = await fixture(html`

el.errorState = true;
el.modelValue = 'bar';
mimicUserInput(el, 'bar');
expect(formatterSpy.callCount).to.equal(1);
expect(el.formattedValue).to.equal('foo: init-string');
expect(el.formattedValue).to.equal('bar');
el.errorState = false;
el.modelValue = 'bar2';
mimicUserInput(el, 'bar2');
expect(formatterSpy.callCount).to.equal(2);

@@ -229,0 +248,0 @@

@@ -22,2 +22,7 @@ import {

function mimicUserInput(formControl, newViewValue) {
formControl.value = newViewValue; // eslint-disable-line no-param-reassign
formControl.inputElement.dispatchEvent(new CustomEvent('input', { bubbles: true }));
}
beforeEach(() => {

@@ -332,3 +337,3 @@ localizeTearDown();

it('will only update formattedValue the value when valid', async () => {
it('will only update formattedValue when valid on `user-input-changed`', async () => {
const formatterSpy = sinon.spy(value => `foo: ${value}`);

@@ -353,5 +358,5 @@ function isBarValidator(value) {

lionField.modelValue = 'foo';
mimicUserInput(lionField, 'foo');
expect(formatterSpy.callCount).to.equal(1);
expect(lionField.formattedValue).to.equal('foo: bar');
expect(lionField.formattedValue).to.equal('foo');
});

@@ -358,0 +363,0 @@ });

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc