diff --git a/packages/formik/README.md b/packages/formik/README.md index b9e1bf3..25738cf 100644 --- a/packages/formik/README.md +++ b/packages/formik/README.md @@ -16,22 +16,19 @@ npm install @domain-schema/formik @domain-schema/core @domain-schema/validation ## Usage -##### NOTE: The current version works properly for the web platform only. React Native forms support will be added soon. +##### NOTE: The current version properly works only for the web platform. Support for React Native forms will be added soon. ### Example #### Simple form -This is example how you can generate basic form according to schema: +The simple form - is a form generated by this package and based on domain-schema without + fields with nested schema. +This is how domain-schema without complex fields looks: ```js -import DomainSchema, { Schema } from '@domain-schema/core'; -import { DomainSchemaFormik } from '@domain-schema/formik'; - -import { Button, Form, RenderField } from '../my-components'; - -const userFormSchema = class User extends Schema { __ = { name: 'User' }; - username = { + id = DomainSchema.Int; + name = { type: String, input: { label: 'Username' @@ -53,16 +50,10 @@ const userFormSchema = }, min: 5 }; - passwordConfirmation = { - type: String, - input: { - type: 'password', - label: 'Password Confirmation', - }, - matches: 'password' - }; } - +``` +This is how you can generate a basic form according to schema: +```js // set components globally for all forms DomainSchemaFormik.setFormComponents({ input: RenderField, @@ -70,7 +61,7 @@ DomainSchemaFormik.setFormComponents({ button: Button }); -const userForm = new DomainSchemaFormik(userFormSchema); +const userForm = new DomainSchemaFormik(User); const UserForm = userForm.generateForm({ label: 'Save' @@ -82,81 +73,45 @@ const UserForm = userForm.generateForm({ ``` #### Complex form -The complex form - it is the form that has the nested schema field which represents -relations with other schema. So, when one to one relation established - -form with flat structure will be generated by default. Also, you could use ```fieldType``` property -with ```form``` value to explicitly set up such behaviour. -```js -const userFormSchema = +A complex form meaning the form that has a nested schema field that represents +relations with the other schema. + +##### Advanced schema with One-To-One relationships +One-To-One is the relationship between two entities. A and B in which one element of A may only be linked +to one element of B, and vice versa. +The One-To-One relation between schemas is shown in the code sample below. + + ```js class User extends Schema { __ = { name: 'User' }; - username = { - type: String, - input: { - label: 'Username' - }, - defaultValue: 'User', - validators: [ - value => { - return value.length > 3 ? undefined : 'Must Be more than 3 characters'; - } - ] - }; - email = { - type: String, - input: { - type: 'email', - label: 'Email', - placeholder: 'User email' - }, - email: true - }; profile = { type: Profile }; - password = { - type: String, - input: { - type: 'password', - label: 'Password', - }, - min: 5 - }; - passwordConfirmation = { - type: String, - input: { - type: 'password', - label: 'Password Confirmation', - }, - matches: 'password' - }; - } - + } + + class Profile extends Schema { + __ = { name: 'Profile' }; + user = { + type: User + }; + } + ```` + So, when One-To-One relation established - form with flat structure will be generated by default. Meaning + nested schema fields will be inserted into the form. +Also, you could use ```fieldType``` property +with the value ```form``` to explicitly set up such behaviour. +```js class Profile extends Schema { __ = { name: 'Profile' }; - firstName = { - type: String, - input: { - label: 'First Name' - }, - required: { - value: true, - msg: 'Required First Name' - } - }; - lastName = { - type: String, - input: { - label: 'Last Name' - }, - optional: true - }; user = { - type: User + type: User, + fieldType: 'form' } } - -const userForm = new DomainSchemaFormik(userFormSchema); +``` +This is how you can generate a complex form according to schema: +```js +const userForm = new DomainSchemaFormik(User); // set components for particular DomainSchemaFormik instance userForm.setFormComponents({ @@ -165,88 +120,40 @@ userForm.setFormComponents({ button: Button }); -// change error messages -DomainValidation.setValidationMessages({ - required: ({fieldName}) => { - return `Field '${fieldName}' is required` - } -}); - -const UserForm = userForm.generateForm( - { - label: 'Submit', - className: 'submit-btn', - disableOnInvalid: false - }, - { className: 'my-form' } -); +const UserForm = userForm.generateForm(); // Defining onSubmit prop is required { // handle submit }}> ``` +##### Advanced schema with One-To-Many relationships -When established one to many relation, the nested schema field which implements -this relation (Group has many users) will be skipped by default. But -for nested schema with belonging relation (User belongs to Group) fieldType ```select``` will be applied. +One-To-Many is relationship between two entities. A and B in which an element of A may be linked to many elements of B, +but a member of B is linked to only one element of A. The one-to-many relation between schemas is shown in the code sample below. ```js class Group extends Schema { __ = { name: 'Group' }; - id = { - type: DomainSchema.Int - }; - name = { - type: String, - input: { - label: 'Group Name' - } - }; - description = { - type: String, - input:{ - label: 'Group Description' - } - }; + // this field will be skipped by default users = { type: [User] }; } class User extends Schema { __ = { name: 'User' }; - id= { - type: DomainSchema.Int - }; - name = { - type: String, - input: { - type: 'text', - label: 'Username' - }, - }; - email = { - type: String, - input: { - type: 'email', - label: 'Email', - placeholder: 'User email' - } - }; + // for this field fieldType select will be defined by default group = { type: Group }; - password = { - type: String, - input: { - type: 'password', - label: 'Password' - }, - min: 5 - }; } - +``` +The field, with the nested schema, which implements has many relationship, will be not included in the form + by default. + But for the nested schema with belonging relation field type ```select``` will be defined by default. +This is how you can generate a complex form according to schema: +```js const groupForm = new DomainSchemaFormik(Group); // set components for particular DomainSchemaFormik instance @@ -257,46 +164,42 @@ groupForm.setFormComponents({ button: Button }); -const GroupForm = groupForm.generateForm( - { - label: 'Submit', - className: 'submit-btn', - disableOnInvalid: false - } -); +const GroupForm = groupForm.generateForm(); // Defining onSubmit prop is required { // handle submit }}> ``` -To prevent generating field use ``ignore`` flag. +##### Advanced schema with Many-To-Many relationships +Current functionality in development + ### Using different field types -To pass attributes/properties to the field component use ```input``` property in a schema. All fields can take 3 special attributes: ```onChange```, ```onBlur``` and ```type```. All other defined attributes will be directly passed to the field component. Attribute ```name``` will be define automatically and equals field name from the schema. +When creating your schemas, you can pass various attributes to the fields. +To pass attributes or properties to the field component, you can use ```input``` property in a schema. All fields can +take three special attributes: ```onChange```, ```onBlur``` and ```type```. All other defined attributes will be passed + to the field component. The attribute ```name``` is define automatically and set to the field name of the field that you + taken from the schema. -* ```input``` - is default field type and it can be omitted +* ```input``` - is default ```fieldType``` and it can be omitted ```js email = { - ... fieldType: 'input', input: { type: 'email', placeholder: 'User Email' } - ... } post = { - ... // fieldType: 'input' input: { placeholder: 'Your post', type: 'textarea', label: 'Post' } - ... } ``` @@ -304,7 +207,6 @@ To pass attributes/properties to the field component use ```input``` property in ```js active = { - ... fieldType: 'checkbox', input: { label: 'Active' @@ -317,13 +219,11 @@ To pass attributes/properties to the field component use ```input``` property in ```js role = { - ... fieldType: 'select', input: { label: 'User role', values: ['user', 'admin'] } - ... } ``` @@ -331,17 +231,15 @@ To pass attributes/properties to the field component use ```input``` property in ```js friend = { - ... fieldType: 'radio', input: { label: 'Very best friend', values: ['Gerald', 'Ashley'] }, - ... } ``` -To prevent the generation of a specific field we can use ```ignore``` property +To prevent generation of a specific field we can use ```ignore``` property ```js password = { @@ -375,7 +273,6 @@ To create a ```submit``` button in the form we need to pass object with attribut All attributes, that we define in the object will be passed to the button: ```js - ... userForm.generateForm({ label: 'Submit', className: 'submit-btn', @@ -392,7 +289,9 @@ By default, ```submit``` button is disabled when form is invalid. To deactivate }) ``` -In some cases, the submit button is not enough for us. We should pass object that has ```submit``` and ```reset``` propperties. ```Reset``` button resets the form-data to its initial values. +In some cases, providing a reset button for the user can be convenient. To create a reset button, we need +to pass an object to ```generateForm``` method with ```submit``` and ```reset``` properties. A ```Reset``` button, +as its name implies will reset form data to the initial (default) values. ```js userForm.generateForm({ @@ -407,62 +306,41 @@ In some cases, the submit button is not enough for us. We should pass object tha }) ``` -For position styling buttons have the `align` property which can take on values ```left``` or ```right```. By default, value is ```center```. +For positioning buttons, you can use the `align` property on a form, ```align``` + can take values ```left``` or ```right```. By default, its value is ```center```. ```js userForm.generateForm({ - ... + label: 'Submit', align: 'left' }) ``` -Buttons are wrapped in a div with style ```display: flex```, so that any properties for flex items can be applied to them. For example, the order of the buttons can be changed using ```order```. - -```css - ... - .submit-btn { - order: 1 - } - .reset-btn { - order: 0 - } - ... -``` - -```js - userForm.generateForm({ - submit: { - ... - className: 'submit-btn' - }, - reset: { - ... - className: 'reset-btn' - } - }) -``` +Buttons are automatically wrapped in a DIV element with style ```display: flex```, so that any +properties for flex items can be applied to them. For example, the order of buttons can be +changed by setting css property order for the element's class. ### Set default field types -Default field types can be set globally. +Default fields types can be set globally. For the common field you can define default ```fieldType``` by +specifying ```plainFieldType``` property. Also you can define the default ```fieldType``` for the field with nested schema +which has One-To-One relationship by specifying ```oneToOneFieldType```. Likewise, you can define the default +```fieldType``` for the field which has One-To-Many relationship by specifying ```oneToManyFieldType```. ```js -... DomainSchemaFormik.setDefaultFormFieldTypes({ oneToOneFieldType: 'form', plainFieldType: 'input', oneToManyFieldType: 'select' }); -... ``` ### Set form components -Form components can be set in two ways. Globally, for all forms: +In order to set which component to render for specific ```fieldType``` you can use ``setFormComponents`` method. Form field - component mapping can be set in two ways. Globally, for all forms: ```js -... DomainSchemaFormik.setFormComponents({ input: RenderField, select: RenderSelect, @@ -470,13 +348,11 @@ DomainSchemaFormik.setFormComponents({ form: Form, button: Button }); -... ``` And locally, for particular DomainSchemaFormik instance: ```js -... const userForm = new DomainSchemaFormik(userFormSchema); userForm.setFormComponents({ @@ -486,12 +362,11 @@ userForm.setFormComponents({ form: Form, button: Button }); -... ``` -### Form submitting +### Submitting a Form -We should define ```onSubmit``` callback which is received values from form fields as ```values``` and helper methods as ```formikBag```. More about these methods in official docs [FormikBag]. +We should define ```onSubmit``` callback which will receive values from form fields as ```values``` and helper methods as ```formikBag```. More about these methods in official docs [FormikBag]. ```js {