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

Term

A term is an expression that evaluates to true / false.

Example:

(!isUserPermitted) and ((name equals `Rachel`) or (name equals `Monica`))

This term is truthy if a user is not permitted to that field and if field name value equals 'Rachel' or 'Monica'.

A term definition and evaluation is used by the form in several parts (such as excludeTerm, disableTerm and requireTerm), in order to evaluate field's flags results.

Example - if you want to exclude a city field from the form's lifecycle, when the country field has no value - define excludeTerm to the field.

Field Term

To define a field term - a definition is required in the model.fields.someField object, and implementation is required in the resources.terms object.

Model

model.fields.someField.someTerm - object - describes a logical regular expression.

Field term is represented by a tree object. A tree node (term) can be one of Conditional term or Logical term:

Conditional term object

NameTypeDescription
operatorrequired stringValues can be one of: 'and' / 'or'
termsrequired arrayArray of terms object (each object can be 'conditional term' or 'logical term' - see below)
notbooleanIf true - the returned value result of the conditional term will become !result

Logical term object

NameTypeDescription
namerequired stringRepresent a key in resources.terms object that this term applies to
argsobjectCustom arguments that the term function gets
notbooleanIf true - logical term returns inverted result

Note: If a term object contains operator - then it is a conditional term. Otherwise we treat it as logical term.

Resources

resources.terms - object. Required only if model.fields.someField.someTerm is defined. Key is the term name, and value is an object that contains:

NameTypeDescription
funcrequired functionReturns term evaluation result (true / false). Function can be sync or async function (that resolves to a boolean value). More info
defaultArgsobjectDefault args for all fields. This will be shallow merged with field level term args before passed to the func

func

function ({ 
  id, 
  value,  
  dependencies { id: { value } },
  args,
  context,
})

return value - boolean. true is pass term, otherwise - false.

Example

excludeTerm is used for this example.

City field is excluded if user is not permitted and country is Mexico or Israel.

Term = (!isUserPermitted) and ((country equals Mexico) or (country equals Israel))

import { isEqual } from 'lodash';

const model = {
  // ...
  fields: {
    country: {
      // ...
    },
    city: {
      // ...
      dependencies: ['country'], // define it in ordered that country's value will be injected to the exclude term func in - prop.dependencies
      excludeTerm: {
        operator: 'and', // conditional term
        terms: [{
          name: 'isUserPermitted', // logical term
          not: true
        }, {
          operator: 'or', // conditional term
          terms: [{
            name: 'equals', // logical term
            args: {
              fieldId: 'country',
              value: 'Mexico',
            }
          }, {
            name: 'equals',  // logical term
            args: {
              fieldId: 'country',
              value: 'Israel',
            }
          }]
        }],
      },
    }
  },
};

// note - 'equals' is a built-in term - therefor not needed here. 
// We added it here just for the example.
const resources = {
  terms: {
    isUserPermitted: {
      func: (props) => {
        let isUserPermitted;
        // ....
        return isUserPermitted;
      },
    },
    equals: {
      func: (props) => {
        const dependantFieldValue = props.dependencies[props.args.fieldId];
        return isEqual(dependantFieldValue, props.args.value);
      },
    }
  }
};

Shorthand

Definition shorthand for terms can be found in definition shorthand documentation.

Built-in Terms

Cofi also defines built-in terms: 'equals', 'lowerThan' and so on. Built-in terms in resources.terms object work out of the box, there's no need to define them in resources.terms. Cofi extends custom terms object (from resources.terms) with the built-in terms object.

  • Define resources.terms object with custom term that is not part of Cofi's built-in terms:

Example

const model = {
  // ...
  fields: {
    // ...
    name: {
      // ...
      excludeTerm :{
        name: 'isUserPermitted',
        not: true
      }
    }
  },
};

const resources = {
  terms: {
    isUserPermitted: {
      func: (props) => {
        let isUserPermitted;
        // ....
        return isUserPermitted;,
      }
    },
  }
}
  • Define field.excludeTerm term that is part of the built-in terms:

Example

const model = {
  // ...
  fields: {
    // ...
    country: {
      // ...
    },
    city: {
      // ...
      dependencies: ['country'],
      excludeTerm :{ // exclude city if country not exists
        name: 'exists',
        not: true,
        args: {
          fieldId: 'country'
        }
      }
    }
  },
}

// no need to define resources.terms
  • Define a field's excludeTerm that is one of Cofi's built-in terms and also define it in resources.terms object in order to override the built-in function behavior (you can also define a custom override for only some of: func / defaultArgs)

Example

const model = {
  // ...
  fields: {
    // ...
    country: {
      // ...
    },
    city: {
      // ...
      dependencies: ['country'],
      excludeTerm :{ // exclude city if country not exists
        name: 'exists',
        not: true,
        args: {
          fieldId: 'country'
        }
      }
    }
  }
};

const resources = {
  terms: {
    exists: {
      func: props => props.dependencies[props.args.fieldId] !== undefined,
    }
  }
};

The following are Cofi's built-in terms and their usage:

empty

Verify if dependency field's value considered empty.

Return true for: undefined, null, {}, [], ''. Otherwise false.

Default args:

NameTypeDefaultDescription
fieldIdstringundefinedDependency field id
contextIdstringundefinedDependency context id

Example:

meetingTime excluded if: meetingMembers is empty

// model.fields.meetingTime
dependencies: ['meetingMembers'],
excludeTerm: {
  name: 'empty',
  args: {
    fieldId: 'meetingMembers',
  }
}

Note: empty term calls isEmpty hook. This hook is also called from other parts of the form's lifecycle. So in order to keep form integrity (i.e field is considered empty in all lifecycle parts the same way), you should only override this hook instead of the empty term.

Example:

  • isEmpty default implementation return true when value is '' (empty string) among others.
  • Only empty term is overridden to a different logic than isEmpty hook - only undefined considered empty.
  • Country field value is '' - therefor is required and empty (i.e a "required" error message appears)
  • City field has defined excludeTerm to be excluded when Country is empty.
  • Result: City is not excluded even though Country is empty.

exists

Verify if dependency's field value exists.

Return true for: undefined, null. Otherwise false.

Default args:

NameTypeDefaultDescription
fieldIdstringundefinedDependency field id
contextIdstringundefinedDependency context id

Example:

city excluded if: country doesn't exist

// model.fields.city
dependencies: ['country'],
excludeTerm: {
  name: 'exists',
  not: true,
  args: {
    fieldId: 'country',
  }
}

equals

Verify if dependency field's value equals to args.value. (performs abstract comparisons).

Default args:

NameTypeDefaultDescription
fieldIdstringundefinedDependency field id
contextIdstringundefinedDependency context id
valueanyundefinedCompared to dependency's field value

Example:

seasonNumber excluded if: contentType doesn't equal 'SERIES'

// model.fields.seasonNumber
dependencies: ['contentType'],
excludeTerm: {
  name: 'equals',
  not: true,
  args: {
    fieldId: 'contentType',
    value: 'SERIES',
  }
}

lowerThan

Verify if dependency field's value lower than args.value.

Default args:

NameTypeDefaultDescription
fieldIdstringundefinedDependency field id
contextIdstringundefinedDependency context id
valueanyundefinedCompared to dependency's field value

Example:

adultsContent excluded if: age is lower than 18

// model.fields.adultsContent
dependencies: ['age'],
excludeTerm: {
  name: 'lowerThan',
  args: {
    fieldId: 'age',
    value: 18,
  }
}

lowerThan is truthy if args.fieldId's value is less than args.value

lowerThanOrEquals

Verify if dependency field's value lower than or equals to args.value.

Default args:

NameTypeDefaultDescription
fieldIdstringundefinedDependency field id
contextIdstringundefinedDependency context id
valueanyundefinedCompared to dependency's field value

Example:

adultsContent excluded if: age is lower than or equals 18

// model.fields.adultsContent
dependencies: ['age'],
excludeTerm: {
  name: 'lowerThanOrEquals',
  args: {
    fieldId: 'age',
    value: 18,
  }
}

lowerThanOrEquals is truthy if args.fieldId's value is lower than or equals to args.value

greaterThan

Verify if dependency field's value greater than args.value.

Default args:

NameTypeDefaultDescription
fieldIdstringundefinedDependency field id
contextIdstringundefinedDependency context id
valueanyundefinedCompared to dependency's field value

Example:

'kidsContent' excluded if: 'age' is greater than 18

// model.fields.kidsContent
dependencies: ['age'],
excludeTerm: {
  name: 'greaterThan',
  args: {
    fieldId: 'age',
    value: 18,
  }
}

greaterThan is truthy if args.fieldId's value is more than args.value

greaterThanOrEquals

Verify if dependency field's value greater than or equals to args.value.

Default args:

NameTypeDefaultDescription
fieldIdstringundefinedDependency field id
contextIdstringundefinedDependency context id
valueanyundefinedCompared to dependency's field value

Example:

'kidsContent' excluded if: 'age' is greater than or equals 18

// model.fields.kidsContent
dependencies: ['age'],
excludeTerm: {
  name: 'greaterThanOrEquals',
  args: {
    fieldId: 'age',
    value: 18,
  }
}

greaterThanOrEquals is truthy if args.fieldId's value is greater than or equals to args.value

equalsOne

Verify if dependency field's value equals to one of the values in args.value.

Default args:

NameTypeDefaultDescription
fieldIdstringundefinedDependency field id
contextIdstringundefinedDependency context id
valuearray[]Compared to dependency's field value

Example:

secondaryColor excluded if: 'color equals to one of these values: ["GREEN", "BLUE", "BLACK"]. (color field is a string value)

// model.fields.secondaryColor
dependencies: ['color'],
excludeTerm: {
  name: 'equalsOne',
  args: {
    fieldId: 'color',
    value: ["GREEN", "BLUE", "BLACK"],
  }
}

equalsOne performs abstract comparisons, meaning args.value can be array of any type of object.

includes

Verify if dependency field's value includes args.value (performs abstract comparisons, meaning args.value can be any objects).

Default args:

NameTypeDefaultDescription
fieldIdstringundefinedDependency field id
contextIdstringundefinedDependency context id
valueanyundefinedCompared to dependency's field value

Example:

secondaryColor excluded if: colors includes "GREEN". (colors field is a string array value)

// model.fields.secondaryColor
dependencies: ['colors'],
excludeTerm: {
  name: 'includes',
  args: {
    fieldId: 'colors',
    value: "GREEN",
  }
}

includesAll

Verify if dependency field's value includes all of the values in args.value (performs abstract comparisons, meaning args.value can be array of any objects).

Default args:

NameTypeDefaultDescription
fieldIdstringundefinedDependency field id
contextIdstringundefinedDependency context id
valuearray[]Compared to dependency's field value

Example:

secondaryColor excluded if: colors includes all of the following values: ["GREEN", "BLUE", "BLACK"]. (colors field is a string array value)

// model.fields.secondaryColor
dependencies: ['colors'],
excludeTerm: {
  name: 'includesAll',
  args: {
    fieldId: 'colors',
    value: ["GREEN", "BLUE", "BLACK"],
  }
}

includesOne

Verify if dependency field's value includes at least one of the values in args.value (performs abstract comparisons, meaning args.value can be array of any objects).

Default args:

NameTypeDefaultDescription
fieldIdstringundefinedDependency field id
contextIdstringundefinedDependency context id
valuearray[]Compared to dependency's field value

Example: secondaryColor excluded if: colors includes any of these values: ["GREEN", "BLUE", "BLACK"]. (colors field is a string array field)

// model.fields.secondaryColor
dependencies: ['colors'],
excludeTerm: {
  name: 'includesOne',
  args: {
    fieldId: 'colors',
    value: ["GREEN", "BLUE", "BLACK"],
  }
}
← HooksLog →
  • Field Term
    • Model
    • Resources
    • Example
    • Shorthand
  • Built-in Terms
    • empty
    • exists
    • equals
    • lowerThan
    • lowerThanOrEquals
    • greaterThan
    • greaterThanOrEquals
    • equalsOne
    • includes
    • includesAll
    • includesOne
cofi
Copyright © 2021 Verizon Media
DOCS
IntroductionForm ClassReact FormReact ComponentsReact Layout
DEMOS
React FormReact ComponentsReact Layout
CONTRIBUTING
Code Of ConductContributing GuideContributorsUsers
CHANNELS
StarGitHubStack OverflowMediumVideos