New form generator is in the hood! Welcome Jafar 🌟

Gal Havivi
5 min readFeb 17, 2020

--

Jafar — !(Just another form application renderer) is a new open source monorepo which we at Verizon Media (Yahoo + Aol) have recently shared on Github.

Managing complicated forms is a hard task for developers. Dealing with field validations, dependencies, disable or exclude fields in some conditions and more can make the code complicated, hard to maintain and hard to write to begin with.

Jafar let developers build forms easily by defining a readable and intuitive form definition (model json & resources json) that represent the entire form lifescycle — such as fields and their corresponding data path, initial data, validators, dto conversions and more. It’s based on a pure javascript, ui free form class which handles the form’s definition, lifecycle and data manipulations. With the basic form class, any ui library (such as react, angular and vue) can easily use it to expose Form and Field components.

Jafar contains integration to react using 3 main packages:

  1. @jafar/react-form — which exposes Form and Field react components. Internally it uses @jafar/form — base Form class which handles all the form lifecycle. Form and Field components are only meant to be a thin UI layer that lets the users a way to communicate with the internal form — i.e send actions to the form (such as change field value), and receive the updated form information to present the user.
  2. @jafar/react-components — which exposes all kind of common components such as Text, Number and Select to help you get started quickly. These component are only meant to be a mapper layer to an underline real UI components (we mostly use Material UI components as underline components). Since Jafar knows how to work with any custom component — it requires from the components it uses in the form to implement a specific interface of props and callbacks (such as value prop and onValueChange callback prop). You can also use your own custom components with Jafar as long as you are implementing Jafar’s components interface.
  3. @jafar/react-layout — currently exposes a page layout component which contains header, sections that can render fields, footer with actions, options menu, mobile layout and responsive layout.

We use all of the 3 above packages in our systems to create a unified and consistent layout among our internal management applications to create manage pages for our system’s entities — Create, Edit, Details and List pages.

What will you gain from implementing your management pages with Jafar?

  1. It’s a huge time consuming. Iv’e been working at Verizon Media for 6 and a half years now (originally at Aol which was bought by Verizon). In that period of time Aol bought Vidible company which had similar business, Verizon bought Aol, and later Verizon bought Yahoo. All of these purchases — along with sticking to the latest UI libraries (jQuery then Angular and now React) brought us to integrate systems and re-create our management pages in our internal systems each time from scratch. It takes massive time to get into other companies and other developers code, especially if it uses a non familiar technology (to you), and i’m not talking about pages with 5–6 fields. Im talking about massive pages with 20–50 fields, that contains a lot of complicated condition (for example if field A changes — then field B should disappear, or be disabled or change its value), permissions, and more headache — especially when you don’t have an organised spec. Good luck with that!
    Using Jafar ensures that any time you want to change UI framework (for example from angular to react), all your form logic remains the same and un-touched, since all the “spec” of the form is already defined in the form model & resources objects (which are pure javascript).
  2. It provides a consist and intuitive spec, so when a new developer needs to maintain these pages, all he needs to do is to take a quick glance of the form model (i.e its spec) and immediately he can understand anything that goes on in the form. Moreover — using it for all your management pages creates a unified “language” that all pages follow.
  3. Unified and consistent layout among all your system. You can define all your components in a single place, and use them across all you pages. If a component for example needs a ui change — it will immediately appear in all of the pages that uses this component.
  4. Many useful capabilities — such as persist a form between page refreshes, using the same form spec for a server side validation in a node server (which also save duplication of client and server developers work), use it in grid — where each row can be a form, and each cell can be a field, save snapshot of the form on each change — which can give ability of undo operation, history, restore form for debug users bug cases and more.

Simple example

Install Jafar’s packages:

npm install @jafar/react-form 
npm install @jafar/react-components

Create the form configuration. For the simplicity let’s create a form.js file which contains 2 fields — first name and last name. First name is require and must have at least 2 characters:

import TextInput from '@jafar/react-components/edit/Text';const resources = {
components: {
TextInput
},
hooks: {
submit: async ({ data }) => {
// save data to server...
}
}
};
const model = {
id: 'employee-form',
fields: {
firstName: {
path: 'firstname',
label: 'First Name',
required: true,
validators: [{
name: 'minLength',
args: { value: 2 },
}],
component: {
name: 'TextInput',
state: {
placeholder: 'Enter first name'
}
}
},
lastName: {
path: 'lastname',
label: 'Last Name',
component: {
name: 'TextInput',
state: {
placeholder: 'Enter last name'
}
}
}
}
}
export default { model, resource };
  • I recommend to follow Jafar’s folder structure as a practice to all your forms, to have a strait forward and organised structure.

Pass the form configuration to the Form component (here i used the helper function of createForm which only wraps the given Demo component with a Form component):

import React, { useContext } from 'react';
import { createForm, FormContext } from '@jafar/react-form';
import Button from '@material-ui/core/Button';
import employeeForm from './form';
const Demo = () => {
const form = useContext(FormContext);
const save = () => {
await form.actions.sumbit();
// do anything...
}
return (<div>
<h2>Basic Info</h2>
<Field id="firstName" />
<Field id="lastName" />
<Button
disabled={
!form.model.dirty
|| form.model.invalid
|| form.model.processing
}
onClick={save}>Save</Button>
</div>);
}

export default createForm(employeeForm)(Demo);

Thats it! Once I used Jafar i was not able to go back implementing manage pages without it again. It will save you development time (and we all know time equals money), duplication of code, headache sweat and tears!

Jafar’s docs & demos — https://yahoo.github.io/jafar/

--

--