cofi

cofi

  • Docs
  • Form Demos
  • Components Demos
  • Layout Demos
  • Editor
  • GitHub

›Form Class

Getting started

  • Introduction

Form Class

  • Installation
  • Overview
  • Arguments
  • Id
  • Data
  • Fields
  • Path
  • Component
  • Formatter & Parser
  • Dependencies
  • Required
  • Validators
  • Exclude Term
  • Disable Term
  • Require Term
  • Dependencies Change
  • Context
  • Dirty
  • Invalid
  • Errors
  • Processing
  • Pending Actions
  • Hooks
  • Term
  • Log
  • Error Codes
  • Actions
  • Definition Shorthand

Advanced Usages

  • Grid Usage
  • Form Persistency
  • Undo & Redo
  • Replay Actions
  • Track Actions
  • Server Validation
  • Entity Templates
  • Folder Structure

React Form

  • Installation
  • Overview
  • Form
  • Field
  • Components
  • Layout
  • Demos

Tools

  • Editor
  • DevTools

More Info

  • Test Cofi
  • Packages
  • Why Cofi?
  • Technologies
  • Videos
  • Channels

Contribute

  • Code of Conduct
  • Contributing Guide
  • Contributors

Error Codes

MISSING_ID

model.id is missing. More info

Example

const model = { // id is missing
}

Solution

const model = {
  id: 'employeeForm'
  // ...
}

MISSING_DATA

model.data should be an object. More info

Example

const model = { // data is invalid
  data: []
  // ...
}

Solution

const model = {
  data: {}
  // ...
}

MISSING_FIELDS

model.fields should be an object with at least one field defined. More info

Example

const model = { // fields is missing
}

const model = { // fields is array (should be a object)
  fields: [{
    id: 'name',
    // ...
  }]
}

const model = { // fields is empty (should be at least one field defined)
  fields: {
  }
}

Solution

const model = {
  fields: {
    name: {
      // ...
    }
  }
  // ...
}

MISSING_FIELD_PATH

field fieldId should define path. More info

Example

const model = {
  fields: {
    name: { // name is missing path
    }
  }
  // ...
}

Solution

const model = {
  fields: {
    name: {
      path: 'name',
      // ...
    }
  }
  // ...
}

MISSING_COMPONENT

field fieldId defined a component, in the model, which do not match the definition in resources object. Example: for model.fields.firstName.component = { name: 'InputText' }, define resources.components.InputText = { renderer: MyComponent }. More info

Example

const model = {
  fields: {
    firstName: { 
      component: { 
        name: 'InputText',
      }
    }
  }
};

const resources = {
  components: {
    // missing InputText
  }
};

Solution

import MyInputComponent from './components/MyInputComponent.jsx';

const model = {
  fields: {
    firstName: { 
      component: { 
        name: 'InputText',
      }
    }
  }
};

const resources = {
  components: {
    InputText: { 
      renderer: MyInputComponent 
    }
  }
};

INVALID_STATE_CHANGE

component name defined a stateChange handler, which is not a function. More info

Example

import AsyncSelect from './components/AsyncSelect'

const model = {
  fields: {
    hobbies: { 
      component: { 
        name: 'AsyncSelect',
      }
    }
  }
};

const resources = {
  components: {
    AsyncSelect: {
      renderer: AsyncSelect,
      stateChange: '', // should be a function (if defined)
    }
  }
};

Solution

import AsyncSelect from './components/AsyncSelect'

const model = {
  fields: {
    hobbies: { 
      component: { 
        name: 'AsyncSelect',
      }
    }
  }
};

const resources = {
  components: {
    AsyncSelect: {
      renderer: AsyncSelect,
      stateChange: (props) => {
        // ...
      }
    }
  }
};

REDUNDANT_CONVERSION

field fieldId defined a conversionName named name in the model without defining a component. More info

Note: conversionName can be formatter or parser.

Example

const model = {
  fields: {
    age: { 
      formatter: { name: 'ageFormatter' },
      // missing component
    }
  }
};

Solution

const model = {
  fields: {
    age: { 
      component: {  // add a component definition or remove the formatter definition
        name: 'inputNumber',
      },
      formatter: { name: 'ageFormatter' },
    }
  }
};

MISSING_CONVERSION

field fieldId defined a conversionName named name in the model, which should match a definition in resources object - resources.conversions.name = { func: () => {} }. More info

Note: conversionName can be formatter or parser.

Example

const model = {
  fields: {
    age: { 
      component: { 
        name: 'inputNumber',
      },
      formatter: { name: 'ageFormatter' },
    }
  }
};

const resources = {
  conversions: {
    // missing ageFormatter
  }
};

Solution

const model = {
  fields: {
    age: { 
      component: { 
        name: 'inputNumber',
      }
      formatter: { name: 'ageFormatter' },
    }
  }
};

const resources = {
  conversions: {
    ageFormatter: {
      func: (props) => {
        // ...
      }
    }
  }
};

MISSING_FORMATTER_OR_PARSER

field fieldId defined only one of parser or formatter, but for editable component both formatter and parser should be defined.

Example

const model = {
  fields: {
    age: { 
      component: { 
        name: 'inputNumber',
      },
      parser: { name: 'ageParser' },
      // missing formatter
    }
  }
  // ...
}

Solution

const model = {
  fields: {
    age: { 
      component: { 
        name: 'inputNumber',
      },
      parser: { name: 'ageParser' },
      formatter: { name: 'ageFormatter' },
    }
  }
  // ...
}

MISSING_DEPENDENCIES_FIELD

field fieldId defined a dependency on field dependOnField in dependencies, but dependOnField is not defined in model.fields. More info

Example

const model = {
  fields: {
    city: { 
      // ...
      dependencies: ['country'],
    }
    // country field is not defined
  }
  // ...
}

Solution

const model = {
  fields: {
    city: { 
      // ...
      dependencies: ['country'],
    }
    country: { 
      // ...
    }
  }
  // ...
}

MISSING_DEPENDENCIES_CHANGE

field fieldId defined a dependenciesChange, named name in the model, which should match a definition in resources object - resources.dependenciesChanges.name = { func: () => {} }. More info

Example

const model = {
  fields: {
    city: { 
      dependencies: ['country'],
      dependenciesChange: { name: 'cityDependenciesChange' },
    },
    country: { 
      // ...
    }
  },
};

const resources = {
  dependenciesChanges: {
    // missing cityDependenciesChange
  },
};

Solution

const model = {
  fields: {
    city: { 
      dependencies: ['country'],
      dependenciesChange: { name: 'cityDependenciesChange' },
    },
    country: { 
      // ...
    }
  },
};

const resources = {
  dependenciesChanges: {
    cityDependenciesChange: {
      func: (props) => {
        // ...
      }
    }
  }
};

MISSING_VALIDATOR

field fieldId defined a validator, named name in the model, which should match a definition in resources object - resources.validators.name = { func, message }. More info

Example

const model = {
  fields: {
    name: { 
      // ...
      validators: [{
        name: 'uniqueName',
      }],
    }
  },
};

const resources = {
  validators: {
    // missing uniqueName / missing uniqueName.func / missing uniqueName.message
  },
};

Solution

const model = {
  fields: {
    name: { 
      // ...
      validators: [{
        name: 'uniqueName',
      }],
    }
  },
};

const resources = {
  validators: {
    uniqueName: {
      func: (props) => {
        // ...
      },
      message: (props) => {
        // ...
      },
    }
  },
};

MISSING_TERM

field fieldId defined a term intermsType, namednamein the model, which should match a definition in resources object - resources.termsType.name = { func: () => {} } More info

Note: termsType can be excludeTerm, disableTerm or requireTerm.

Example

const model = {
  fields: {
    name: { 
      // ...
      excludeTerm: [{
        name: 'myCustomTerm',
      }],
    }
  },
};

const resources = {
  terms: {
    // missing myCustomTerm
  },
};

Solution

const model = {
  fields: {
    name: { 
      // ...
      excludeTerm: [{
        name: 'myCustomTerm',
      }],
    }
  },
};

const resources = {
  terms: {
    myCustomTerm: {
      func: (props) => {
        // ...
      }
    } 
  }
};

MISSING_HOOKS

resources.hooks should be an object. More info

Example

const resources = { // hooks is invalid
  hooks: []
  // ...
}

Solution

const resources = {
  hooks: {}
  // ...
}

INVALID_HOOK

hook hook is not supported. More info

Example

const resources = { 
  hooks: {
    beforeChangeField: () => {}, // hook is not supported
  }
  // ...
}

Solution

const resources = {
  hooks: {
    beforeChangeValue: () => {},
  }
  // ...
}

INVALID_SETTING

setting setting is invalid. Expected to be expected. More info

Example

const settings = {
  changeValueDebounceWait: '200',
}

Solution

const settings = {
  changeValueDebounceWait: 200,
}

INVALID_SUBMIT

can't perform submit when form is invalid. More info

Example

// model.invalid is true

context.actions.submit();

Solution

// model.invalid is false. You can add a disable condition to your submit function such as 
// <Button disabled={this.context.model.invalid} 
// onClick={() => { await this.context.actions.submit() }}>Submit</Button>

context.actions.submit();

CIRCULAR_DEPENDENCIES

field fieldId of form formId defined circular dependencies: dependenciesStr. More info

Meaning: changeFieldValue action was called with the same field id and value more than one time in the same field evaluation.

Example

initial values: a=0, b=0, c=0. User changes "a" to 1, causes:

a=1 -> b=2 -> c=1 -> b=2

If we will not stop and throw an error we will get infinit loop of:

a=1 -> b=2 -> c=1 -> b=2 -> c=2 -> b=2 -> c=3 -> b=2 -> c=4 -> b=2 ->.....

Cofi prefer throw an error rather than stop the loop itself, inorder that the user will know about its circular dependencies definition, and will fix it using an exit code.

const model = {
  // ...
  fields: {
    a: {
      // ...
    }, 
    b: {
      // ...
      dependencies: ['a', 'c'],
      dependenciesChange”: 'bDependenciesChange',
    },
    c: {
      // ...
      dependencies: ['b'],
      dependenciesChange”: 'cDependenciesChange',
    }, 
  }, 
};

const resources = {
  dependenciesChanges: {
    bDependenciesChange: {
      func: (props) => ({ value: 2 }),
    },
    cDependenciesChange: {
      func: (props) => ({ value: props.value + 1 }),
    }
  }
};

Solution

define an exit case in at least one of the dependenciesChange function.

const model = {
  // ...
  fields: {
    a: {
      // ...
    }, 
    b: {
      // ...
      dependencies: ['a', 'c'],
      dependenciesChange”: 'bDependenciesChange',
    },
    c: {
      // ...
      dependencies: ['b'],
      dependenciesChange”: 'cDependenciesChange',
    }, 
  },
};

const resources = {
  dependenciesChanges: {
    bDependenciesChange: {
      func: (props) => ((props.dependencies.a.value < 2 && props.dependencies.c.value < 2) ? { value: 2 } : undefined),
    },
    cDependenciesChange: {
      func: (props) => ({ value: props.value + 1 }),
    },
  }
};

MAX_CIRCULAR_DEPENDENCIES_LOOPS

field fieldId of form formId has reached maximum circular dependencies loops (maxChangeValueLoops): dependenciesStr. More info

Meaning: changeFieldValue action was called with the same field id with different value for maxChangeValueLoops times in the same field evaluation, causing a loop that might not end.

Example

const model = {
  // ...
  fields: {
    a: {
      // ...
      dependencies: ['b'],
      dependenciesChange”: 'aDependenciesChange',
    }, 
    b: {
      // ...
      dependencies: ['a'],
      dependenciesChange”: 'bDependenciesChange',
    }
  },
};

const resources = {
  dependenciesChanges: {
    aDependenciesChange: {
      func: (props) => ({ value: props.value + 1 }),
    },
    bDependenciesChange: {
      func: (props) => ({ value: props.value + 1 }),
    },
  }
};

Solution

define an exit case in at least one of the dependenciesChange function.

  • “a” changes
    • triggers “b” to change value (in dependencyChange func return value to change)
      • triggers “a” to change value (in dependencyChange func return value to change)
        • triggers “b” to evaluate (in dependencyChange func return undefined)

a = 0, b = 0. a changes to 1 -> triggers b change to 1 -> triggers a change to 2 -> trigger b to return undefined and not change anything. loop ends.

const model = {
  // ...
  fields: {
    a: {
      // ...
      dependencies: ['b'],
      dependenciesChange”: 'aDependenciesChange',
    }, 
    b: {
      // ...
      dependencies: ['a'],
      dependenciesChange”: 'bDependenciesChange',
    }
  }
};

const resources = {
  dependenciesChanges: {
    aDependenciesChange: {
      func: (props) => {
        if (props.dependencies.b.value < 2) {
          return { value: props.value + 1 };
        }
        return undefined; // exit case
      },
    },
    bDependenciesChange: {
      func: (props) => {
        if (props.dependencies.a.value < 2) {
          return { value: props.value + 1 };
        }
        return undefined; // exit case
      },
    },
  }
};

CHANGE_VALUE_UPDATER_NOT_SUPPORTED

calling changeValue action with an updater function is not supported for a field without a component. More info

Example

import Form from '@cofi/form';

// define user form
const model = {
  id: 'user-form',
  fields: {
    size: { // size field is missing a component
      path: 'size',
    },
  },
  data: {
    size: { x: 1, y: 1 },
  }
};

// create user form
const form = new Form();
await form.init(model, resources);

// change size field value - with an updater function
await form.changeValue('size', ({ value }) => ({ x: value.x + 1, y: value.y + 1 }));

Solution

import Form from '@cofi/form';

// define user form
const model = {
  id: 'user-form',
  fields: {
    size: {
      path: 'size',
      component: { // add a component to the field
        name: 'Dimensions',
      },
    },
  },
  data: {
    size: { x: 1, y: 1 },
  }
};

const resources = {
  components: {
    Dimensions: { renderer: Dimensions },
  },
};

// create user form
const form = new Form();
await form.init(model, resources);

// change size field value - with an updater function
await form.changeValue('size', ({ value }) => ({ x: value.x + 1, y: value.y + 1 }));

ACCESS_DESTROYED_FORM

can't access destroyed form. More info

Example

import Form from '@cofi/form';

const model = { /* ... */ };

const resources = { /* ... */ };

// create form
const form = new Form();
await form.init(model, resources);

// destroy form
await form.destroy();

// change value
await form.changeValue('firstName', 'Rachel'); // throws error

Solution

import Form from '@cofi/form';

const model = { /* ... */ };

const resources = { /* ... */ };

// create form
const form = new Form();
await form.init(model, resources);

// destroy form
await form.destroy();

// don't access form instance anymore

INVALID_LOG_LEVEL

log level logLevel is not supported. Supported log levels are: debug, warn, error and none. More info

Example

import { setLogLevel } from '@cofi/form';

setLogLevel('bla');

Solution

import { setLogLevel, logLevels } from '@cofi/form';

setLogLevel(logLevels.DEBUG);

INVALID_LOG_FUNCTION

log type is not a function. More info

Example

import { setLogger } from '@cofi/form';

setLogger({ error: 'bla' });

Solution

import { setLogger } from '@cofi/form';

setLogger({ error: (props) => { /* ... */ } });

ACTION_FAILED

action name failed. An action fails due to an exception which occurs in one of the supplied resources handlers such as: validators, terms, conversions, dependenciesChanges, stateChange and hooks. Look on the sub error for more info. Try to debug your custom handler's code, or verify that parameters passed to build-in validators are correct with same expected type. More info.

Example

import Form from '@cofi/form';

// define user form
const model = {
  id: 'user-form',
  fields: {
    children: {
      path: 'children',
      validators: [{ name: 'aboveAge', args: { age: 14 } }],
    },
  },
};

const resources = {
  validators: {
    aboveAge: {
      func: ({ value, args }) => {
        return !value.find(x => x.age < args.age); // this with cause an exception when value is undefined
      },
      message: () => 'All children must be above 14.',
    },
  },
};

// create user form
const form = new Form();
await form.init(model, resources);

Solution

import Form from '@cofi/form';

// define user form
const model = {
  id: 'user-form',
  fields: {
    children: {
      path: 'children',
      validators: [{ name: 'aboveAge', args: { age: 14 } }],
    },
  },
};

const resources = {
  validators: {
    aboveAge: {
      func: ({ value = [], args }) => { // define a default empty array for the expected value
        return !value.find(x => x.age < args.age); 
      },
      message: () => 'All children must be above 14.',
    },
  },
};

// create user form
const form = new Form();
await form.init(model, resources);
← LogActions →
  • MISSING_ID
  • MISSING_DATA
  • MISSING_FIELDS
  • MISSING_FIELD_PATH
  • MISSING_COMPONENT
  • INVALID_STATE_CHANGE
  • REDUNDANT_CONVERSION
  • MISSING_CONVERSION
  • MISSING_FORMATTER_OR_PARSER
  • MISSING_DEPENDENCIES_FIELD
  • MISSING_DEPENDENCIES_CHANGE
  • MISSING_VALIDATOR
  • MISSING_TERM
  • MISSING_HOOKS
  • INVALID_HOOK
  • INVALID_SETTING
  • INVALID_SUBMIT
  • CIRCULAR_DEPENDENCIES
  • MAX_CIRCULAR_DEPENDENCIES_LOOPS
  • CHANGE_VALUE_UPDATER_NOT_SUPPORTED
  • ACCESS_DESTROYED_FORM
  • INVALID_LOG_LEVEL
  • INVALID_LOG_FUNCTION
  • ACTION_FAILED
cofi
Copyright © 2021 Verizon Media
DOCS
IntroductionForm ClassReact FormReact ComponentsReact Layout
DEMOS
React FormReact ComponentsReact Layout
CONTRIBUTING
Code Of ConductContributing GuideContributorsUsers
CHANNELS
StarGitHubStack OverflowMediumVideos