## principle: Convention over configuration
only needs to specify unconventional aspects of the application by config

### develop
开发分支在dev 发布分支在master
the way how you look at an app
### Conventions
- state structure {`moduleName`List, `moduleName`}
- action name load`moduleName`List  load`moduleName`
- field in table and editable

### helpers && keywords
keywords used to trigger a predefined action or expand  a predefined object

helpers used to generate config object easily

#form-tpl
## how to use
```html
 <FormTpl
    :model="formData"
    :fields="config.form"
    v-if="config.form"
    :options="{inline: true, nativeOn: {click: onSearch}}">
    <!--optional: some slot here -->
 </FormTpl>
```
### how to write fields
fields is an array like:
```js
[
      {
        type: 'input',
        label: 'SLS Tracking Order ID',
        key: 'sls_tracking_number',
        rule: {
          'sls_tracking_number': [{
                type: 'number',
                message: `${key} should be a number !`
              }
        }]
      },
      {
        type: 'input',
        label: 'Shopee Order SN',
        key: 'shopee_order_sn'
      },
      {
        type: 'select',
        label: 'Status',
        key: 'status',
        options: RECEIVE.STATUS.map((val, index) => ({
          value: index.toString(),
          label: val
        })),
        options: {
          on: {
            change: 'submit'
          }
        }
      },
      {
          type: 'date-picker',
          subType: 'datetimerange',
          label: 'Pick Up Time',
          key: 'pick_up_time',
          placeholder: ['start time', 'end time']
      }
   ]
```
writing this object by hand can be bored,
so the following pattern is recommended, using helper which provided by package

```js
new FieldInput('Email', 'email', ['required', 'email']),
new FieldInput('Phone', 'phone', true),
new FieldSelect('Status', 'status', [
   ...USER.STATUS.map((item, index) => ({
      label: item,
      value: index
   }))
], true),
new FieldMultiSelect('Role', 'role_list', () => {
   return this.roleOptions
}, true),
```
hint: two ways to pass options: array or function which return an array,
functional way is necessary when options is dynamic

form-tpl provide many keyword to ease your writing,
```js
options: {
   on: {
      change: 'submit'
    }
}
```
instand of writing function handler, form submitting can be triggered by a string 'submit'

| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| form | `optional` hold the reference of form component, used to get form status | Object | null |
| model | hold all the value user have input | Object | {} |
| fields | defined the form input | Array | [] |
| rules | `optional` to specify the validation rules, can be written in `fields` | Object | null |
| options | `optional` to specify the trivial things like layout | Object | null |
