lion/packages/field/src/FormRegistrarMixin.js
2019-11-01 13:11:29 +01:00

121 lines
3.6 KiB
JavaScript

import { dedupeMixin } from '@lion/core';
import { formRegistrarManager } from './formRegistrarManager.js';
import { FormRegisteringMixin } from './FormRegisteringMixin.js';
/**
* This allows an element to become the manager of a register
*/
export const FormRegistrarMixin = dedupeMixin(
superclass =>
// eslint-disable-next-line no-shadow, no-unused-vars
class FormRegistrarMixin extends FormRegisteringMixin(superclass) {
get formElements() {
return this.__formElements;
}
set formElements(value) {
this.__formElements = value;
}
get formElementsArray() {
return this.__formElements;
}
constructor() {
super();
this.formElements = [];
this.__readyForRegistration = false;
this.__hasBeenRendered = false;
this.registrationReady = new Promise(resolve => {
this.__resolveRegistrationReady = resolve;
});
this._onRequestToAddFormElement = this._onRequestToAddFormElement.bind(this);
this.addEventListener('form-element-register', this._onRequestToAddFormElement);
}
connectedCallback() {
if (super.connectedCallback) {
super.connectedCallback();
}
formRegistrarManager.add(this);
if (this.__hasBeenRendered) {
formRegistrarManager.becomesReady();
}
}
disconnectedCallback() {
if (super.disconnectedCallback) {
super.disconnectedCallback();
}
formRegistrarManager.remove(this);
}
isRegisteredFormElement(el) {
return this.formElementsArray.some(exitingEl => exitingEl === el);
}
firstUpdated(changedProperties) {
super.firstUpdated(changedProperties);
this.__resolveRegistrationReady();
this.__readyForRegistration = true;
formRegistrarManager.becomesReady();
this.__hasBeenRendered = true;
}
addFormElement(child, index) {
// This is a way to let the child element (a lion-fieldset or lion-field) know, about its parent
// eslint-disable-next-line no-param-reassign
child.__parentFormGroup = this;
if (index > 0) {
this.formElements.splice(index, 0, child);
} else {
this.formElements.push(child);
}
}
removeFormElement(child) {
const index = this.formElements.indexOf(child);
if (index > -1) {
this.formElements.splice(index, 1);
}
}
_onRequestToAddFormElement(ev) {
const child = ev.detail.element;
if (child === this) {
// as we fire and listen - don't add ourselves
return;
}
if (this.isRegisteredFormElement(child)) {
// do not readd already existing elements
return;
}
ev.stopPropagation();
// Check for siblings to determine the right order to insert into formElements
// If there is no next sibling, index is -1
let indexToInsertAt = -1;
if (this.formElements && Array.isArray(this.formElements)) {
indexToInsertAt = this.formElements.indexOf(child.nextElementSibling);
}
this.addFormElement(child, indexToInsertAt);
}
_onRequestToRemoveFormElement(ev) {
const child = ev.detail.element;
if (child === this) {
// as we fire and listen - don't add ourselves
return;
}
if (!this.isRegisteredFormElement(child)) {
// do not readd already existing elements
return;
}
ev.stopPropagation();
this.removeFormElement(child);
}
},
);