Make underlying form a slot.
This commit is contained in:
@@ -1,23 +1,80 @@
|
||||
/**
|
||||
* This is the object that ties a group of inputs to a name.
|
||||
* It assumes that every input in the group is of the same type.
|
||||
*/
|
||||
class Field {
|
||||
|
||||
private _type: string;
|
||||
|
||||
constructor(private name: string, private _inputs: FieldElement[]) {
|
||||
if (this._inputs.length === 0) {
|
||||
throw new Error("[Declaform] Error: cannot construct Field with empty inputs array.")
|
||||
}
|
||||
this._type = this._inputs[0]!.type;
|
||||
}
|
||||
|
||||
get value() {
|
||||
switch(this._type) {
|
||||
case 'checkbox':
|
||||
return (this._inputs as HTMLInputElement[]).filter(x => x.checked).map(x => x.value);
|
||||
case 'radio':
|
||||
return (this._inputs as HTMLInputElement[]).find(x => x.checked)?.value;
|
||||
default:
|
||||
case 'date':
|
||||
case 'datatime-local':
|
||||
case 'email':
|
||||
case 'number':
|
||||
case 'password':
|
||||
case 'select':
|
||||
case 'text':
|
||||
// can assert this._inputs[0]! because we throw Error in constructor if _inputs.length = 0
|
||||
return (this._inputs.length > 1) ? this._inputs.map(x => x.value) : this._inputs[0]!.value;
|
||||
}
|
||||
}
|
||||
|
||||
set value(x: any) {
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this._type;
|
||||
}
|
||||
}
|
||||
|
||||
export class Declaform extends HTMLElement {
|
||||
|
||||
static observedAttributes = [
|
||||
'customInputs', // Lets user specify additional inputs to be considered "fields" by the form. Example: <object-list>
|
||||
'src', // defines api endpoint used to hydrate this object
|
||||
'action', // defines api endpoint used to submit this object to
|
||||
'method', // defines http method to use on "action" endpoint
|
||||
]
|
||||
|
||||
/* The character that gets used to join multiple field values */
|
||||
static joining_char = ',';
|
||||
|
||||
private _fields: Field[];
|
||||
private _form: HTMLFormElement;
|
||||
private _form: HTMLFormElement | null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.attachInternals();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
this.shadowRoot!.innerHTML = '<form><slot></slot></form>';
|
||||
this.shadowRoot!.innerHTML = '<slot name="form"></slot>';
|
||||
this._fields = [];
|
||||
this._form = this.shadowRoot!.querySelector('form')!;
|
||||
this._form = null;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const formSlot = this.shadowRoot?.querySelector('slot[name="form"]') as HTMLSlotElement;
|
||||
if (!formSlot) {
|
||||
throw new Error('[Declaform] Error: "form" slot is unassigned.')
|
||||
}
|
||||
if (formSlot.assignedElements()[0]?.tagName !== 'FORM') {
|
||||
throw new Error('[Declaform] Error: "form" slot must be assigned to a <form>.')
|
||||
}
|
||||
this._form = formSlot.assignedElements()[0] as HTMLFormElement;
|
||||
|
||||
const customInputs = this.getAttribute('customInputs')?.split(',').map(x => x.trim()) ?? [];
|
||||
const selectors = ['input', 'select'].concat(customInputs).map(x => `${x}[name]`).join(',');
|
||||
const inputs = Array.from(this.querySelectorAll(selectors));
|
||||
@@ -73,42 +130,4 @@ function isFieldElement(x: unknown): x is FieldElement {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the object that ties a group of inputs to a name.
|
||||
* It assumes that every input in the group is of the same type.
|
||||
*/
|
||||
class Field {
|
||||
|
||||
/* The character that gets used to join multiple field values */
|
||||
static joining_char = ',';
|
||||
|
||||
private _type: string;
|
||||
|
||||
constructor(private name: string, private _inputs: FieldElement[]) {
|
||||
if (this._inputs.length === 0) {
|
||||
throw new Error("[Declaform] Error: cannot construct Field with empty inputs array.")
|
||||
}
|
||||
this._type = this._inputs[0]!.type;
|
||||
}
|
||||
|
||||
get value() {
|
||||
switch(this._type) {
|
||||
default:
|
||||
case 'date':
|
||||
case 'datatime-local':
|
||||
case 'email':
|
||||
case 'number':
|
||||
case 'text':
|
||||
return this._inputs.map(x => x.value);
|
||||
}
|
||||
}
|
||||
|
||||
set value(x: any) {
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this._type;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user