gd-bs
Version:
Bootstrap JavaScript, TypeScript and Web Components library.
230 lines (190 loc) • 6.68 kB
text/typescript
import { IForm, IFormProps, IFormRow } from "./formTypes";
import { IFormControl, IFormControlProps } from "./controlTypes";
import { Base } from "../base";
import { FormControl as Control } from "./control";
import { FormGroup } from "./group";
import { FormRow } from "./row";
import { HTML } from "./templates";
import { FormValidationTypes } from "./types";
export * from "./custom";
export * from "./types";
/**
* Form
* @property props - The form properties.
*/
class _Form extends Base<IFormProps> implements IForm {
private _groups: Array<FormGroup> = null;
private _rows: Array<FormRow> = null;
// Constructor
constructor(props: IFormProps) {
super(HTML, props);
// Configure the form
this.configure();
// Configure the events
this.configureEvents();
// Configure the parent
this.configureParent();
}
// Configure the form
private configure() {
// Clear the groups and rows
this._groups = [];
this._rows = [];
// Add the class name
let classNames = (this.props.className || "").split(" ");
for (let i = 0; i < classNames.length; i++) {
let className = classNames[i];
// Append the class name
className ? this.el.classList.add(className) : null;
}
// Set the floating class
this.props.isFloating ? this.el.classList.add("form-floating") : null;
// Append the controls
this.appendControls(this.props.controls)
// Append the rows
this.appendRows(this.props.rows);
}
// Configure the events
private configureEvents() {
// See if an onrendered event exists
if (this.props.onRendered) {
// Wait before executing the rendered event, otherwise the controls will be null
let intervalId = setInterval(() => {
let isLoaded = true;
// Parse the controls
for (let i = 0; i < this.controls.length; i++) {
let control = this.controls[i];
// Set the flag
isLoaded = isLoaded && control && control.isRendered;
}
// See if the form is loaded
if (isLoaded) {
// Clear the interval
clearInterval(intervalId);
// Execute the event
this.props.onRendered(this.controls);
}
}, 10);
}
}
/**
* Public Interface
*/
// Append controls to the form
appendControls(controls: Array<IFormControlProps> = []) {
// Parse the controls
for (let i = 0; i < controls.length; i++) {
// Create the group
let group = new FormGroup(controls[i], this.props);
this._groups.push(group);
this.el.appendChild(group.el);
}
}
// Append rows to the form
appendRows(rows: Array<IFormRow> = []) {
// Parse the rows
for (let i = 0; i < rows.length; i++) {
// Create the row
let row = new FormRow(rows[i], this.props);
this._rows.push(row);
this.el.appendChild(row.el);
}
}
// The forms controls
get controls() {
let controls: Array<IFormControl> = [];
// Parse the groups
for (let i = 0; i < this._groups.length; i++) {
// Add the control
controls.push(this._groups[i].control);
}
// Parse the rows
for (let i = 0; i < this._rows.length; i++) {
// Add the controls
controls = controls.concat(this._rows[i].controls);
}
// Return the controls
return controls;
}
// Gets a form control by its name
getControl(name: string) {
// Parse the controls
let controls = this.controls;
for (let i = 0; i < controls.length; i++) {
let control = controls[i];
// See if this is the control we are looking for
if (control && control.props && control.props.name == name) {
// Return the control
return control;
}
}
// Control not found
return null;
}
// Gets the form values
getValues() {
let values = {};
// Parse the controls
let controls = this.controls;
for (let i = 0; i < controls.length; i++) {
let control = controls[i];
if (control.props.name) {
// Set the value
values[control.props.name] = control.getValue();
}
}
// Return the values
return values;
}
// Inserts a control into the form
insertControl(idx: number, control: IFormControlProps) {
// Create the group
let group = new FormGroup(control, this.props);
this._groups.push(group);
// Validate the index
if (idx < this.el.childElementCount) {
// Insert the control
this.el.insertBefore(group.el, this.el.childNodes[idx]);
} else {
// Append the control
this.el.appendChild(group.el);
}
}
// Validates the form
isValid() {
let isValid = true;
// Parse the controls
let controls = this.controls;
for (let i = 0; i < controls.length; i++) {
// See if this control is valid
if (controls[i].isValid == false) {
// Set the flag
isValid = false;
}
}
// Update the classes
this.el.classList.remove("needs-validation");
this.el.classList.add("was-validated");
// Return the flag
return isValid;
}
}
export const Form = (props: IFormProps): IForm => { return new _Form(props); }
/**
* Form Control
*/
export const FormControl = (props: IFormControlProps) => {
// Create a base object
let base = new Base("", props);
// Create the control
let control = new Control(props, { validationType: FormValidationTypes.Default });
// Wait for the control to be loaded
control.isLoaded().then(() => {
// Set the element
base.el = control.el;
// Configure the parent
base.configureParent();
});
// Return the control
return control;
}