Skip to content

Commit

Permalink
Add radio name group control (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
nizniz187 committed Sep 5, 2021
1 parent af33d02 commit 8e69c95
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 32 deletions.
8 changes: 4 additions & 4 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@
<input type="checkbox" name="native" value="5" /> Native Checkbox
<!-- Radio -->
<w-heading level="3" underlined="true">Radio</w-heading>
<w-radio>Un-Checked</w-radio>
<w-radio checked>Checked</w-radio>
<w-radio disabled>Un-Checked Disabled</w-radio>
<w-radio checked disabled>Checked Disabled</w-radio>
<w-radio name="radio" value="radio1">Un-Checked</w-radio>
<w-radio name="radio" checked value="radio2">Checked</w-radio>
<w-radio name="radio" disabled value="radio3">Un-Checked Disabled</w-radio>
<w-radio name="radio" checked disabled value="radio4">Checked Disabled</w-radio>

<button type="submit">SUBMIT</button>
</w-form>
Expand Down
4 changes: 4 additions & 0 deletions wc/WComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class WComponent extends HTMLElement{
this.componentWillRender();
this.render();
this.componentDidRender();
this.key = new Date().getTime();
}

componentWillRender() {}
Expand Down Expand Up @@ -60,6 +61,9 @@ class WComponent extends HTMLElement{
});
});
}
equals(component) {
return this.key === component.key;
}
getAttributeParserByName(name) {
if(typeof name !== 'string') {
return undefined;
Expand Down
71 changes: 43 additions & 28 deletions wc/components/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ class Form extends WComponent{
const formData = new FormData();
const elements = Array.from(this.querySelectorAll(FORM_ELEMENT_TYPES));
elements.forEach(elem => {
if(typeof elem.name === 'string' && elem.value !== null && elem.value !== undefined) {
if((elem.type === 'checkbox' || elem.type === 'radio') && !elem.checked) {
// Exclude unchecked checkbox & radio
return;
}
const existingValue = formData.get(elem.name);
if(existingValue === null) {
formData.set(elem.name, elem.value);
} else if(Array.isArray(existingValue)) {
existingValue.push(elem.value);
} else {
formData.set(elem.name, [existingValue, elem.value]);
}
// Exclude elements with invalid name or value
if(typeof elem.name !== 'string' || typeof elem.value !== 'string') { return; }
// Exclude unchecked checkbox & radio
if(elem.type === 'checkbox' && !elem.checked) { return; }
if(elem.type === 'radio' && !elem.checked) { return; }

const existingValue = formData.get(elem.name);
if(existingValue === null) {
formData.set(elem.name, elem.value);
} else if(Array.isArray(existingValue)) {
existingValue.push(elem.value);
} else {
formData.set(elem.name, [existingValue, elem.value]);
}
});
return formData;
Expand Down Expand Up @@ -64,8 +64,12 @@ class Form extends WComponent{
const slot = this.shadowRoot.querySelector('slot');
slot.addEventListener('slotchange', () => this.bindFormAccess());

// Bind submit event on submit button click
const submitBtn = this.querySelector('input[type="submit"], button[type="submit"]');
submitBtn.addEventListener('click', this.submitHandler);

// Bind radio click callback for name group control
this.querySelectorAll('w-radio').forEach(radio => radio.addEventListener('click', this.radioClickCallback));
}
/**
* Bind direct form access from document by name.
Expand All @@ -82,23 +86,23 @@ class Form extends WComponent{
* Dynamically add getters & setters for form elements to get direct access by name.
*/
bindFormElementAccess() {
// Bind direct form elemnt access from form by name
this.querySelectorAll(FORM_ELEMENT_TYPES).forEach(elem => {
if(typeof elem.name === 'string'
&& !Object.getOwnPropertyDescriptor(this, elem.name)) {
// Dynamically add getter if there is none defined.
Object.defineProperty(this, elem.name, {
get: () => {
const list = Array.from(this.querySelectorAll(`[name='${elem.name}']`));
if(list.length > 1) {
const value = list.filter(item => item.checked).map(item => item.value);
list.value = value.length === 1 ? value[0] : value;
return list;
}
return list.length === 0 ? undefined : list[0];
// Exclude elements with invalid name
if(typeof elem.name !== 'string') { return; }
// Exclude elements which getters are already set
if(Object.getOwnPropertyDescriptor(this, elem.name)) { return; }

Object.defineProperty(this, elem.name, {
get: () => {
const list = Array.from(this.querySelectorAll(`[name='${elem.name}']`));
if(list.length > 1) {
const value = list.filter(item => item.checked).map(item => item.value);
list.value = value.length === 1 ? value[0] : value;
return list;
}
});
}
return list.length === 0 ? undefined : list[0];
}
});
});
}
render() {
Expand All @@ -112,6 +116,17 @@ class Form extends WComponent{
DOM.create('slot', {}, form);
}

radioClickCallback = e => {
const radio = e.target;
if(typeof radio.name !== 'string' || radio.disabled) { return; }

const radios = Array.from(this.querySelectorAll(`w-radio[name='${radio.name}']`));
radios.forEach(r => {
if(!r.equals(radio)) {
r.checked = false;
}
});
}
submitHandler = e => {
this.dispatchEvent(this.events.submit);
this.shadowRoot.querySelector('form').submit();
Expand Down

0 comments on commit 8e69c95

Please sign in to comment.