Skip to content

Instantly share code, notes, and snippets.

@Super-Chama
Created March 7, 2022 12:32
Show Gist options
  • Save Super-Chama/6d6b3af421e1b18b7de0156dea2d86ff to your computer and use it in GitHub Desktop.
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',
},
},
],
},
],
},
],
};
@lgtkaushalya
Copy link

Here are my comments.

  1. Will we have a scenario where some rows will have 3 widgets while the other rows have 2 widgets. How can we support it? Is it through the class?
  2. What can we achieve through the hooks. An example
  3. How to control button actions such as to avoid double click behaviors

@icechathuranga
Copy link

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.

@manojpsw
Copy link

manojpsw commented Mar 8, 2022

  1. 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.

  2. How can we bind standard js events to FieldSchema and is there a way to bind and remove events.

  3. 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>;
};

`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment