-
-
Save Super-Chama/6d6b3af421e1b18b7de0156dea2d86ff to your computer and use it in GitHub Desktop.
import {ConcreteComponent, CSSProperties} from 'vue'; | |
export const TYPE_BUTTON = 'button'; | |
export const TYPE_INPUT = 'input'; | |
export const TYPE_FILE_INPUT = 'file'; | |
export const TYPE_TEXTAREA = 'textarea'; | |
export const TYPE_DROPDOWN = 'dropdown'; | |
export const TYPE_PASSWORD = 'password'; | |
export const TYPE_CHECKBOX = 'checkbox'; | |
export const TYPE_SWITCH = 'switch'; | |
export const TYPE_RADIO = 'radio'; | |
export const TYPE_DATE = 'date'; | |
export const TYPE_AUTOCOMPLETE = 'autocomplete'; | |
export const TYPE_SELECT = 'select'; | |
export const TYPE_MULTISELECT = 'multiselect'; | |
export const TYPE_TIME = 'time'; | |
export const TYPE_GRID = 'grid'; | |
export const TYPE_INLINE = 'inline'; | |
export const TYPE_ACTION = 'action'; | |
export const TYPE_DIVIDER = 'divider'; | |
export type FieldType = | |
| typeof TYPE_BUTTON | |
| typeof TYPE_INPUT | |
| typeof TYPE_FILE_INPUT | |
| typeof TYPE_TEXTAREA | |
| typeof TYPE_DROPDOWN | |
| typeof TYPE_PASSWORD | |
| typeof TYPE_CHECKBOX | |
| typeof TYPE_SWITCH | |
| typeof TYPE_RADIO | |
| typeof TYPE_DATE | |
| typeof TYPE_AUTOCOMPLETE | |
| typeof TYPE_SELECT | |
| typeof TYPE_MULTISELECT | |
| typeof TYPE_TIME; | |
export type LayoutType = | |
| typeof TYPE_GRID | |
| typeof TYPE_INLINE | |
| typeof TYPE_ACTION | |
| typeof TYPE_DIVIDER; | |
type FieldSchema<T = object> = { | |
name: string; | |
label: string; | |
type: FieldType | 'custom'; | |
component?: ConcreteComponent; | |
props?: object; | |
value?: string | number | T | Array<T>; | |
placeholder?: string; | |
visible?: boolean; | |
asterisk?: boolean; | |
style?: CSSProperties; | |
class?: Array<string>; | |
hook?: (schema: FieldSchema, model: object) => FieldSchema; | |
validation?: Array<(value: any) => boolean | string>; | |
}; | |
type LayoutChild = { | |
slot?: string; | |
fields?: Array<FieldSchema>; | |
}; | |
type LayoutSchema = { | |
style?: CSSProperties; | |
class?: Array<string>; | |
type: LayoutType | 'custom'; | |
component?: ConcreteComponent; | |
props?: object; | |
children?: Array<LayoutChild>; | |
}; | |
type FormSchema = { | |
style?: CSSProperties; | |
class?: Array<string>; | |
layout: Array<LayoutSchema>; | |
}; | |
// model, validation and layout all in one | |
const formSchema: FormSchema = { | |
layout: [ | |
{ | |
type: 'grid', | |
props: { | |
columns: 2, | |
}, | |
children: [ | |
{ | |
slot: 'default', | |
fields: [ | |
{ | |
name: 'resume', | |
label: 'Select resume', | |
type: 'file', | |
asterisk: true, | |
class: ['--span-column-2'], | |
validation: [ | |
required, | |
validateFile( | |
['text/plain', 'text/rtf', 'text/csv', 'application/csv'], | |
1024 * 10, | |
), | |
], | |
}, | |
{ | |
name: 'firstName', | |
label: 'First Name', | |
type: 'input', | |
asterisk: true, | |
validation: [string, required], | |
}, | |
{ | |
name: 'middleName', | |
label: 'Middle Name', | |
type: 'input', | |
validation: [string], | |
}, | |
{ | |
name: 'lastName', | |
label: 'Last Name', | |
type: 'input', | |
asterisk: true, | |
validation: [string, required], | |
}, | |
{ | |
name: 'email', | |
label: 'Email', | |
type: 'input', | |
visible: true, | |
asterisk: true, | |
hook: (schema: FieldSchema, model: object) => { | |
// do any manipulation to this field based on model data | |
return schema; | |
}, | |
style: { | |
color: 'red', | |
}, | |
validation: [ | |
string, email, required | |
] | |
}, | |
{ | |
name: 'contactNumber', | |
label: 'Contact Number', | |
type: 'input', | |
asterisk: true, | |
validation: [string, required] | |
}, | |
{ | |
name: 'vacancy', | |
label: 'Vacancy', | |
type: 'select', | |
props: { | |
options: [ | |
{id: 1, label: 'Vaccancy One'}, | |
{id: 2, label: 'Vaccancy Two'}, | |
], | |
}, | |
asterisk: true, | |
validation: [selectOption, required] | |
}, | |
{ | |
name: 'date', | |
label: 'Date of Application', | |
type: 'date', | |
validation: [date, nullable] | |
}, | |
], | |
}, | |
], | |
}, | |
{ | |
type: 'divider', | |
class: ['full-width'], | |
}, | |
{ | |
type: 'action', | |
children: [ | |
{ | |
slot: 'right', | |
fields: [ | |
{ | |
name: 'reset', | |
label: 'Reset', | |
type: 'button', | |
props: { | |
type: 'reset', | |
displayType: 'ghost', | |
}, | |
}, | |
{ | |
name: 'submit', | |
label: 'Submit', | |
type: 'button', | |
class: ['orangehrm-left-space'], | |
props: { | |
type: 'submit', | |
displayType: 'secondary', | |
}, | |
}, | |
], | |
}, | |
], | |
}, | |
], | |
}; |
It's better to derive the modal of the form by reading the form schema.
addition to that, asterisk: true may be used to mark the label as required, Can we rename asterisk as required, if that is set to true, the widget will automatically apply the required validation as well (or push the required validation to the validation array from the processing level).
Different input fields may have different ways of checking required validation for getting it to a property level will help in the long run.
-
Is there any possibility to add an id attribute to FieldSchema type and label of input widget should be associated with it explicitly. either user can set the id attribute or if not id should be auto-generated with pattern
formName_fieldName
and label of the field should be associate with id. -
How can we bind standard js events to FieldSchema and is there a way to bind and remove events.
-
Can we add layout presenter logic to class level and anybody can write is there presenter logic as they want
`interface FormLayoutPresenter{
render(): string;
}
class FormGridLayout implements FormLayoutPresenter{
render(): string {
return 'This is Template for form rendering';
}
}
type LayoutSchema = {
style?: CSSProperties;
class?: Array<string>;
type: FormLayoutPresenter;
component?: ConcreteComponent;
props?: object;
children?: Array<LayoutChild>;
};
`
Here are my comments.