Custom Field Renderers¶
Field renderers are how Skuid renders the data of an individual field within a component—particularly the Form and Table components. Skuid builders may create custom field renderers by writing JavaScript snippets, which allow you to display field data in ways Skuid’s standard field renderers may not be able to while also retaining the context and structure provided by an existing Form or Table component.
If you need to parse the data into a specific format, or use HTML to properly display data within a component, but do not require the extensive capabilities of a whole new component, custom field renderers are a useful tool. They could be used to display an embedded video, represent field values as icons, or style field elements in ways the DSS does not currently support.
Prerequisites and Concepts¶
Creating custom field renderers requires a degree of knowledge in several areas related to JavaScript. This topic assumes you’re already familiar with the concepts covered in the UI code topic.
Usage¶
Create a snippet¶
Field renderers are JavaScript snippets that can be created from the App Composer.
Click the JavaScript tab in the Elements pane.
Click
Add Javascript resource and configure- Resource type: Field Renderer.
- Custom field renderer name: Enter an appropriate name describing your field renderers.
- Snippet body: Edit to include your field renderer JavaScript code.
By creating a snippet in this way, Skuid supplies the boilerplate code with all necessary parameters for a functioning field renderer. This code may be altered as needed as long as the snippet returns a FieldRenderer
with the return
keyword.
Warning
If there are multiple child nodes within your mode functions, be sure to see how to designate distinguishable children below within the UI code topic.
Assign the field renderer¶
To assign a field renderer to a field within a component:
- Click the field within the target component within the canvas.
- Change the Display as property to
Custom
. - Select the field renderer you wish to assign within the Custom field renderer field.
Rendering strategies¶
The readModeStrategy
and editModeStrategy
parameters determine how Skuid will attempt to render the DOM nodes described in the read and edit parameters. The render strategy chosen for these modes affects how you must describe your field renderers.
Note
For more information on the differences between these strategies, see the UI Code topic.
Two render strategies are available for general use:
- Virtual: Utilizes the virtual DOM and the maquette library to quickly render and re-render components. Similar to the rendering used by Skuid’s own Ink components, and compatible with the Design System Studio. To use this render strategy, enter
"virtual"
as the value for the parameter. When usingvirtual
rendering for custom field renderers, you’ll need to write in HyperScript notation. - Element: Renders and re-renders components by directly manipulating the DOM. Similar to v1’s custom field renderers. To use this render strategy, enter
"element"
as the value for the parameter.
The virtual rendering strategy is considered best practice and is advised in almost all field renderer use cases. This strategy leads to performance improvements and cleaner code. In contrast, the element rendering strategy’s direct DOM manipulation is more taxing on the browser. However, it can allow for quick conversion of v1 field renderers or other UI elements written in jQuery-esque syntax
read and edit mode functions¶
After selecting a render strategy, the read and edit parameters are written as functions that determine either the virtual DOM node (VNode) or DOM node that will be rendered when the field enters the appropriate mode. The rendering strategy selected above determines how these mode functions must be written.
Note
Regardless of rendering strategy, custom field renderers are very neutral in their behaviors by default, meaning some of the features of Skuid’s default field renderers (e.g., triggering the row updated event on value changes) are not automatically triggered with custom field renderers. However, this event is included in the boilerplate code supplied for the virtual
rendering strategy.
The fieldComponent
parameter and context¶
Regardless of render strategy, the read
and edit
mode methods both receive fieldComponent
as their parameter. This is the actual field element within the Form or Table component.
One of the most important functions available within the fieldComponent’s CPI is getContext()
. This retrieves the context
object of the current field. Using the information available in this object is the key to creating a dynamic, custom field renderer.
context.element
: The DOM element displayed when theelement
rendering strategy is usedcontext.field
: The field itself as a JavaScript objectcontext.model
: The model of the field, as a skuid.model.Model objectcontext.row
: The row of the field, as a JavaScript objectcontext.value
: The value of the field
It can often be helpful to assign these to variables using destructuring in read
and edit
functions:
1 2 3 4 5 6 7 | read: function (fieldComponent) {
let h = fieldComponent.h,
context = fieldComponent.cpi.getContext();
// Destructure one or more of these variables this way.
let { element, field, model, row, value } = context;
console.log(value); // This would be now be equivalent to context.value.
...
|
Warning
Always ensure child nodes within your mode functions are distinguishable. See the related section in the UI Code topic for more info.
Additional data grid mode features with dataGridOptions
¶
The Table component’s data grid mode has several additional options that determine how a field cell responds to an end user’s actions. These options are passed into the field renderer through with dataGridOptions
.
1 2 3 4 5 6 7 8 9 10 11 12 | dataGridOptions: {
needsFocusToEdit: true,
onCopy(fieldComponent) {
// Custom copy logic code
},
onCut(fieldComponent) {
// Custom cut logic code
},
onPaste(fieldComponent, text) {
// Custom paste logic code
}
}
|
needsFocusToEdit
: Determines whether or not the cell is disabled until the user focuses on it—i.e. requiring the user double click to edit its value. This defaults totrue
, but this may not be desirable for all fields types For example, end users typically want to interact with boolean checkboxes without focusing the cell first.onCopy
andonCut
: Determine what happens when the end user copies or cuts the cell, respectively. ThefieldComponent
calling the renderer is passed into these methods as the first argument.Errors thrown within these methods are caught and shown at runtime as toast messages. For example, a password field could prevent copying values with
new Error("Can't copy passwords");
1 2 3 4 5 6 | onCopy(fieldComponent) {
throw new Error("Can't copy passwords");
},
onCut(fieldComponent) {
throw new Error("Can't cut passwords");
}
|
onPaste
: Determines what happens when the end user pastes within the cell. ThefieldComponent
calling the renderer is passed into the method as the first argument, and the field’s value is passed in as its second argument (text
), so that value can be used for custom paste logic.
When using the virtual rendering strategy¶
If using the virtual
rendering strategy, functions must be written in HyperScript syntax and then must return
the result of that HyperScript function.
CSS definitions are passed in as key-value pairs in the styles
object. These keys can be camelCase or strings that reflect the kebab-case name of the CSS property. For example, the following styles
settings will result in the same CSS values.
1 2 3 4 5 6 | styles: {
fontSize: "20px",
}
styles: {
"font-size": "20px",
}
|
Using the element rendering strategy¶
In contrast to virtual rendering, which requires a HyperScript node be returned, element rendering instead looks to the fieldComponent’s context.element
attribute, which is by default an empty div
.
Changes to this DOM element must be made using standard DOM element APIs and properties. Additional elements must be made using other DOM manipulation APIs like document.createElement()
or jQuery functions a la skuid.$
, and then appended to the context.element
.
After creating the DOM element, the context.element
parameter must then be set to that newly created node. Style variants are not applied.
Troubleshooting¶
Because custom field renderer implementations vary widely by use case, troubleshooting custom code can often be a bit more involved than Skuid’s declarative options. If you’re seeing issues with your field renderers, be sure to try the following:
- Test the runtime of your field renderer and look for errors in the browser console.
- Try
console.log(variable)
statements to see the state of variables at different points in the field renderer. This can be particularly helpful forcontext
. - Consider adding debugger statement as breakpoints.
- If your field renderer has multiple VNodes and you’re seeing odd UI behavior, always ensure those VNodes have unique keys.