New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EZP-27577: Creates <ez-field-edit> #26
Conversation
a412b9a
to
9fce55d
Compare
493e664
to
4c1694a
Compare
demo/ez-field-edit.html
Outdated
|
||
<link rel="import" href="../../iron-demo-helpers/demo-snippet.html"> | ||
<link rel="import" href="../ez-field-edit.html"> | ||
<style is="custom-style" include="demo-pages-shared-styles"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since custom-style
and share styles are not included, is
and include
attributes should be removed
js/ez-field-edit.js
Outdated
@@ -0,0 +1,94 @@ | |||
(function () { | |||
/** | |||
* `<ez-field-edit>` is supposed to wrap one or several HTML5 inputs. It tracks user input, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CS issue: stars should be aligned with the first star in the previous line (example https://github.com/ezsystems/hybrid-platform-ui-core-components/blob/master/js/ez-notification.js#L3) and there should be only one space between the star beginning the line and the text
js/ez-field-edit.js
Outdated
|
||
static get properties() { | ||
return { | ||
'invalid': { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing doc
js/ez-field-edit.js
Outdated
|
||
constructor() { | ||
super(); | ||
this.addEventListener('input', this._checkValidity.bind(this)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should probably be delayed to connectedCallback
(meaning you don't need to define a constructor function)
js/ez-field-edit.js
Outdated
this.querySelectorAll('input, select, textarea').forEach((formElement) => { | ||
valid = formElement.validity.valid; | ||
|
||
this.querySelectorAll('label').forEach((labelElement) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's a logical issue here. The selected label can be attached to another input so in that case most likely, the class ez-invalid
will be added to ez-field-edit
. I think you iterate over formElement.labels
(which means the label must have a for
attribute, those are missing in your test)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that also means you should have a test with a fixture where an input have several labels
js/ez-field-edit.js
Outdated
const parents2 = this._parents(node2); | ||
|
||
for (let i = 0; i < parents1.length; i++) { | ||
if (parents1[i] != parents2[i]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have some doubts if this is really working if node1
and node2
have a different depth. You should improve the test various cases.
test/ez-field-edit.html
Outdated
<template> | ||
<ez-field-edit> | ||
<div id="lowestCommonParent1"> | ||
<label>Field label</label> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
related to comment about search the common ancestor, those fixtures are too simple. Having the label
and the input
with the same parent node is clearly an over simplification
test/ez-field-edit.html
Outdated
<ez-field-edit> | ||
<div id="lowestCommonParent1"> | ||
<label>Field label</label> | ||
<input id="input1" type="text" pattern="\d*"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
id="input1"
is already used above, make sure to have unique ids (and by the way, label
should have a for
attribute)
demo/ez-field-edit.html
Outdated
<template> | ||
<form> | ||
<ez-field-edit> | ||
Simple input: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
put this string and Multiple inputs
in a h1
or something like that, this would help using the demo
js/ez-field-edit.js
Outdated
|
||
this.querySelectorAll('label').forEach((labelElement) => { | ||
if (!valid) { | ||
this._commonAncestor(labelElement, formElement).classList.add('ez-invalid'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should put the invalid class in a const to avoid repeating it and also, I'm not super fan of that class, it's maybe a tad too generic. ez-invalid-input
maybe ?
test/js/ez-field-edit.js
Outdated
|
||
describe('invalid lowest common parentNode between related input and label', function () { | ||
it('should set `ez-invalid` class on the lowest common parentNode', function () { | ||
elementWithMultipleInputs.querySelectorAll('input')[0].value = 'invalid value'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should avoid that because this relies on the order in the fixture. Here you should rather use:
elementWithMultipleInputs.querySelectorAll('#lowestCommonParent1 input').value = 'invalid value';
or given you use the #lowestCommonParent1
element below:
const ancestor = elementWithMultipleInputs.querySelector('#lowestCommonParent1');
ancestor.querySelector('input').value = 'invalid value';
e6ef30a
to
86fbffe
Compare
updated @dpobel |
js/ez-field-edit.js
Outdated
/** | ||
* `<ez-field-edit>` is supposed to wrap one or several HTML5 inputs. It tracks user input, | ||
* and if an input is invalid, sets its own `invalid` property to true. It will also add an | ||
* `ez-invalid` class on the related label. This class will be removed once the input gets valid. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the class has changed, ez-invalid-input
and it now adds the class on the first common label and input ancestor.
js/ez-field-edit.js
Outdated
* `ez-invalid` class on the related label. This class will be removed once the input gets valid. | ||
* | ||
* Warning: each element inside <ez-field-edit> can't own more than one couple <input> + <label> | ||
* Furthermore to connect a <label> to an <input> use `for` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the standard mechanism, no need to add that
js/ez-field-edit.js
Outdated
/** | ||
* Checks whether the inputs are valid or not and set the `invalid` property | ||
* accordingly. | ||
* Also set `ez-invalid-input` class on labels connected to invalid inputs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not on labels
js/ez-field-edit.js
Outdated
} | ||
|
||
/** | ||
* Returns the parentNodes of the given node untill <ez-field-edit>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parent nodes
js/ez-field-edit.js
Outdated
* @param {HTMLElement} node | ||
* @return {Array} | ||
*/ | ||
_parents(node) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's a bad name, _getAncestors
maybe ?
test/ez-field-edit.html
Outdated
<ez-field-edit> | ||
<div id="lowestCommonParent1"> | ||
<label for="input2">Field label</label> | ||
<a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not some most appropriate usage of a
, put a span or a div
test/ez-field-edit.html
Outdated
<template> | ||
<ez-field-edit> | ||
<div> | ||
<a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above regarding a
usage
js/ez-field-edit.js
Outdated
* | ||
* @polymerElement | ||
* @demo demo/ez-field-edit.html | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing a space :)
test/js/ez-field-edit.js
Outdated
|
||
it('should get valid', function () { | ||
element.invalid = true; | ||
element.querySelectorAll('input').value = 42; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this does not what you want to do here :) querySelectorAll
returns a NodeList
on which you add a value
property with the value 42 ie you are not setting the input value :)
test/js/ez-field-edit.js
Outdated
}); | ||
}); | ||
|
||
describe('invalid lowest common parentNode between related input and label', function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the test outline is not super clear, it seems like some cases are not tested or mixed.
I would write something like:
describe('`ez-invalid-input` class', function () {
describe('unique input', function () {
describe('with label', function () {
it('should be set on lowest common ancestor');
it('should be remove from lowest common ancestor');
describe('label deeper than input', function () {
it('should be set on lowest common ancestor');
it('should be remove from lowest common ancestor');
});
describe('input deeper than label', function () {
it('should be set on lowest common ancestor');
it('should be remove from lowest common ancestor');
});
});
describe('without label', function () {
it('should be set on parent node');
it('should be remove from parent node');
});
});
describe('multiple inputs', function () {
describe('with label', function () {
it('should be set on lowest common ancestor');
it('should be remove from lowest common ancestor');
describe('label deeper than input', function () {
it('should be set on lowest common ancestor');
it('should be remove from lowest common ancestor');
});
describe('input deeper than label', function () {
it('should be set on lowest common ancestor');
it('should be remove from lowest common ancestor');
});
});
describe('without label', function () {
it('should be set on parent node');
it('should be remove from parent node');
});
});
});
5835978
to
2baa3cf
Compare
js/ez-field-edit.js
Outdated
|
||
this.querySelectorAll('input, select, textarea').forEach((formElement) => { | ||
const getLabelsForFormElement = (input) => { | ||
const labels = input.id ? this.querySelectorAll(`label[for="${formElement.id}"]`) : []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use input
instead of formElement
, that way this function can be defined outside of the forEach
loop
js/ez-field-edit.js
Outdated
toggleInvalidClass(formElement.parentNode, valid); | ||
} | ||
}); | ||
this.invalid = !!this.querySelectorAll('.ez-invalid-input').length || this.classList.contains('ez-invalid-input'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is quite complicated, given you loop over inputs, why not computing the validity:
let globalValidity = true;
this.querySelectorAll('input, select, textarea').forEach((formElement) => {
// rest of the code
globalValidity = (globalValidity && valid);
});
this.invalid = globalValidity;
js/ez-field-edit.js
Outdated
} | ||
|
||
/** | ||
* Returns the parent nodes of the given node untill <ez-field-edit>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
until
0dd2835
to
ef0fbe4
Compare
JIRA: https://jira.ez.no/browse/EZP-27577
Description
Creates ez-field-edit custom element. Currently this component only handles fields inputs validity.
A bit of CSS for the validation part in ezsystems/hybrid-platform-ui#55
Tests
Demo and unit tested