Skip to content

Instantly share code, notes, and snippets.

@JedWatson
Last active February 20, 2020 13:01
Show Gist options
  • Save JedWatson/8519769 to your computer and use it in GitHub Desktop.
Save JedWatson/8519769 to your computer and use it in GitHub Desktop.
Notes on how to create a new field type for Keystone

Creating new Field Types for KeystoneJS

We're currently working on making it easier to add new field types to KeystoneJS as plugins.

In the meantime, if you'd like to work on your own field type, hopefully this guide will point you in the right direction.

Keystone fields require the following:

  • a {fieldType}.js file in ./lib/fieldTypes that controls the field and encapsulates options support, underscore functions, validation and updating
  • the {fieldType}.js file needs to be included by ./lib/fieldTypes/index.js
  • a form.jade file in ./templates/fields/{fieldType} that renders the form field for the element
  • if the field should be available when creating new items (not all types are) then it'll also need an initial.jade template in ./templates/fields/{fieldType} that renders the form field for the create form
  • unless it's a text-type field with no special formatting for the list view, also add support for it in ./templates/mixins/columns.jade

If the field type requires an async callback to handle updates, e.g. file upload, support should be added to the process method in ./lib/updateHandler.js.

To implement filtering on the field type in the list view, you'll need to add

  • support for it in the processFilters and getSearchFilters methods in ./lib/list.js
  • a template to render the search interface in ./templates/views/list.jade (around line 170 or so) - this should be broken up into search.jade templates with the form.jade, initial.jade ones but it hasn't happened yet!

Finally, some field types add their own client-side javascript or css that needs to be included in ./templates/layout/base.jade. Specific styles for different field types are generally implemented in ./public/styles/keystone/forms.less.

The base field class implements a few built-in options and methods that can be set / overridden by each FieldType class. At the moment, it's strongly recommended you understand how ./lib/field.js (the base class) works, and review some of the ways different field types (in ./lib/fieldTypes) are set up to get a feel for how this works.

Some hints:

In the constructor function you can set options that control how the base Field class sets up field types. These include:

  • this._nativeType - unless you're providing your own addToSchema method, this is the data type that will be added to the mongoose Schema
  • this._underscoreMethods (Array of Strings) - a list of methods on the FieldType class that should be automatically bound as underscore methods to the field
    • methods bound as underscore methods should take item as their first argument. See the crop mthod in ./lib/fieldTypes/text.js for an example.
  • options.nofilter stops the field from being included in the drop-down list of available filters on the list view. Set this if you haven't implemented filtering as described above.
  • options.nosort stops the field from being used to sort in the list view

If you are implementing a complex field type (by which we mean one that stores a complex value, e.g. the markdown field type, or one that implements middleware / virtuals / etc.) you need to override the addToSchema method. Follow an existing example closely, this method needs to add() to this.schema, and should call this.bindUnderscoreMethods().

validateInput and updateItem should almost always be added, again see existing examples.

Please feel free to reach out to @keystonejs on twitter, on our Google Group or comment on this gist if you've got any questions or get stuck!

@skrichten
Copy link

Client-side scripts for specific field types appear to be mostly included by ../templates/views/item.jade as opposed to ../templates/layout/base.jade

@alexander-tsig
Copy link

Can you please provide the example of the structures?
For example, CustomFieldType.js.

@damianamallia
Copy link

Hi, I'm trying out the last keystone release and I noticed that the fields implementation is now different and it is using React. With the past release I was able to create a custom field type by adding folder in my repository including .jade and .js file. Since I don't want to fork the keystone library, I was wandering if it is still possible with the new release to create custom fields and if you have any example or suggestion about how to do it. And is there any retro-compatibility with my old custom fields if I update keystone with version 0.3.6?

@fabripeco
Copy link

Hi, I'm trying to create a custom field type too, so I have the same question of damianamallia. Is there any updated documentation about doing that with React? Is it sufficient to replicate a CustomFieldField.js and a CustomFieldType.js in fields/types and then include this type in admin/src/fields.js file? Waiting for news! :)
Thank you for your reply!!

@jeffreypriebe
Copy link

Current as of Keystone v0.3.12
Updated with some information related to current React field types.

@damianamallia - It looks like currently types have to be in Keystone directly.

@rcreasi
Copy link

rcreasi commented Sep 8, 2015

I was also disappointed to discover that it is no longer possible to add custom field types without modifying the Keystone source. Is there a roadmap for the proposed plugin architecture mentioned above?

@AubreyHewes
Copy link

A, seemingly working, workaround for custom types without forking, is on server startup.. (before keystone)

  • copy custom type directories to keystone (node_modules) directories.. types/templates to correct/expected locations
  • change the node_modules/keystone/lib/fileTypes.js / node_modules/keystone/admin/client/fields.js files to include own types.. either via file string replacement or tools like esprima

Another workaround to adjusting the admin ui (via javascript)

  • on server startup concat your own javascript to node_modules/keystone/admin/public/js/packages.js

Note; above examples are based on node_modules being replaced on an application update/deployment (i.e. container/dokku/heroku et al).. If not within a new container then replacements/concats to files will be persisted through server startups.

@yornaath
Copy link

yornaath commented May 1, 2016

Is something like this in 0.3.17 that is not documented?

@axebox
Copy link

axebox commented Jun 16, 2016

This document needs updating. Referenced paths don't exist as documented. (version 0.3.19)

@sjapps
Copy link

sjapps commented Jul 24, 2016

This is a bummer. I started with keystonejs thinking it was easy to add custom fields (every other CMS i worked with has them).

@Tyguy7
Copy link

Tyguy7 commented Oct 10, 2016

This seems to be very out of date.

@mfferreira
Copy link

bump

@td0
Copy link

td0 commented Oct 31, 2016

bump again

@schoettler
Copy link

bump yet again

@robksawyer
Copy link

This would be great to have.

@jonathan-l-rivera
Copy link

bump

@sivagao
Copy link

sivagao commented Mar 19, 2017

bump

@harmjanluth
Copy link

bump

@gautamsi
Copy link

bump

@JarrydTrokis
Copy link

Is this being worked on?

@drgirasol
Copy link

bump

@denvergj
Copy link

???

@Mukarrim
Copy link

bump

@ericzon
Copy link

ericzon commented Feb 20, 2020

++bump

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment