gd-bs
Version:
Bootstrap JavaScript, TypeScript and Web Components library.
143 lines (125 loc) • 5.34 kB
text/typescript
import { IFormControlProps, IFormControl } from "./controlTypes";
import { IFormProps } from "./formTypes";
import { FormControl } from "./control";
import { HTMLGroup } from "./templates";
import { FormControlTypes } from "./types";
/**
* Form Group
*/
export class FormGroup {
private _control: IFormControl = null;
private _el: HTMLDivElement = null;
private _props: IFormControlProps = null;
private _formProps: IFormProps = null;
// Constructor
constructor(props: IFormControlProps, formProps: IFormProps) {
// Save the properties
this._props = props;
this._formProps = formProps;
// Create the element
let el = document.createElement("div");
el.innerHTML = HTMLGroup;
this._el = el.firstChild as HTMLDivElement;
this._el.className = formProps.groupClassName = formProps.groupClassName || "";
// Configure the control
this.configure();
}
// Configure the row
private configure() {
// Execute the rendering event
this.configureEvents(this._props.onControlRendering as any).then(() => {
// Execute the parent rendering event
this.configureEvents(this._formProps.onControlRendering as any).then(() => {
// Remove the rendering event to prevent a duplicate run
let onControlRendering = this._props.onControlRendering;
this._props.onControlRendering = null;
// Render the control
this.render();
// Update the property
this._props.onControlRendering = onControlRendering;
});
});
}
// Configure the events
private configureEvents(event: (control: IFormControlProps) => PromiseLike<IFormControlProps>): PromiseLike<void> {
// Return a promise
return new Promise((resolve, reject) => {
// Execute the rendering event
let returnVal = event ? event(this._props) : null;
if (returnVal && returnVal.then) {
// Wait for the event to complete
returnVal.then(props => {
// Update the properties
this._props = props;
// Resolve the promise
resolve();
}, reject);
} else {
// Resolve the promise
resolve();
}
});
}
// Renders the control
private render() {
// Update the label
let elLabel = this._el.querySelector("label");
let label = this._props.label || (this._control && this._control.props.label);
if (label) {
// Set the text
elLabel.innerHTML = label;
} else {
// Remove the label
this._el.removeChild(elLabel);
elLabel = null;
}
// Update the description
let elDescription = this._el.querySelector("small") as HTMLElement;
let description = this._props.description || (this._control && this._control.props.description);
if (description) {
// Set the text
elDescription.innerHTML = description;
} else {
// Hide the description
elDescription?.classList.add("d-none");
}
// Set the class name
if (this._props.className) {
// Set the class
this._el.className = [
this._el.className || "",
this._props.className
].join(' ').trim();
}
// Create the control
this._control = new FormControl(this._props, this._formProps, elLabel);
// Wait for the control to be created
this._control.isLoaded().then(() => {
// See if the id/name and control element exists
let controlId = this._props.id || this._props.name;
let elControl = this._control.control && this._control.control.el ? this._control.control.el : null;
elControl = elControl ? elControl.querySelector("input") || elControl.querySelector("select") || elControl : null;
if (controlId && elControl && this._props.type != FormControlTypes.Checkbox) {
// See if the description exists
if (elDescription) {
// Set the id and aria properties
elDescription ? elDescription.id = controlId + "_desc" : null;
elControl.setAttribute("aria-describedby", elDescription.id);
}
// See if the label exists
if (elLabel) {
// Set the id and aria properties
elLabel ? elLabel.id = controlId + "_label" : null;
elControl.setAttribute("aria-labelledby", elLabel.id);
}
}
// Append the control, after the label
elDescription ? this._el.insertBefore(this._control.el, elDescription) : this._el.appendChild(this._control.el);
});
}
/**
* Public Interface
*/
get control() { return this._control; }
get el() { return this._el; }
}