Skip to content

How to add new fields (non relationship fields)

Shaung Cheng edited this page Sep 16, 2019 · 2 revisions

Issue 21: allow more input types in application is a good example to get started. Below summarize the changes needed for a simple field, no complex relationship like one-to-one, one-to-many or many-to-many relationship. We use adding the field notes to application as an example:

Frontend Changes

Data model

application.ts, add the new field, for interface, model class, etc.

Display component

application-component.ts, add a block for displaying the new field.

Do we need a new field component?

If the new field can reuse existing field components like link, input (simple one-line text/time/...), etc, then can skip this step. Otherwise we create a field component. In the case for application.notes, it's a rich text field that uses component CKeditor to generate rich content.

In form-factory/, create a directory for the new field. Each field requires two types of files: a FormField component, and a FormFieldMeta class. It's the easiest to copy an existing field's directory to shadow all the things you need to configure.

The most important part here is the FormField component. Here we create a FormRichTextField. We use Formik's <Field> to scaffold the form infrastructures. The changes needed depends on the type of field you are creating, but the basic ideas are:

  • Initial value: you can retrieve the initial value by field.value, use this as either placeholder or initial value (like loading existing data, think case of edit) for the low-level component (<CKeditor> in this case). The field is provided by Formik <Field>'s render={(field, ...) => ...}.
  • OnChange: when using a non-trivial low level component other than <input >, the way for onChange to retrieve the UI's value is oftentime different than a typical <input>, which is something like event.target.value. In our case, our low-level component <CKeditor> uses editor.getData() to retrieve value. You will get error if you just use {...field} to pass over everything onto <CKeditor>, because formik's onChange by default uses the <input> way (event.target.value). As a result, you need to explicitly implement onChange and take care of setting the formik field value. Luckily, this is not so hard. Basically you use form.setFieldValue(field.name, <the low level component value here>) to inform formik to sync the field's value. Here.
  • Label: this will not affect the actual data, just for UI and readability purpose. This label is specified when instantiating the meta class, and in the field component file here you can use this.props.label to show the label.

And that's most of the cases what you need!

Use the new field component in form component!

In our example, the field notes belongs to application, so we want to add our notes form field component to the application form component. In application form field, you'll new the meta class and add it to this.formFieldPropsList. You can look at the existing newed metas in the list to help you finish.

After adding the meta instance, we should now see the new field appearing in the application form!

Backend Changes

Data model

You'll add a field to the model class. Then do manage.py makemigrations and then migrate.

Serializer

For the application serializer, you'll add the new field to fields = (...., 'new_field_here'), so that it appears in the json response, and will accept this field in POST requests.

Test it out!

Check:

  • Press create application to open the form. Does the new field appeared?
  • Type something in the field, and press saved. Does the display component show the changed field value?
  • Re-login to the app, does the server data gives the changed field value? If so, you can rest assure that the data is propagated to database!