Chapter 3: Fields and Views¶
In the previous chapter, we learned a range of skills, including how to create and use services, work with the Layout component, make the dashboard translatable, and lazy load a JavaScript library like Chart.js. Now, let’s move on to learning how to create new fields and views.
Fields and views are among the most important concepts in the Flectra user interface. They are key to many important user interactions, and should therefore work perfectly.
In the context of the JavaScript framework, fields are components specialized for visualizing/editing a specific field for a given record.
For example, a (Python) model may define a char field, which will be represented by a field
component CharField
.
A field component is basically just a component registered in the fields
registry. The field component may define some additional static keys (metadata), such
as displayName
or supportedTypes
, and the most important one: extractProps
, which prepare the
base props received by the CharField
.
Example
Let us discuss a simplified implementation of a CharField
.
First, here is the template:
<t t-name="web.CharField" owl="1">
<t t-if="props.readonly">
<span t-esc="formattedValue" />
</t>
<t t-else="">
<input
class="o_input"
t-att-type="props.isPassword ? 'password' : 'text'"
t-att-placeholder="props.placeholder"
t-on-change="updateValue"
/>
</t>
</t>
It features a readonly mode and an edit mode, which is an input with a few attributes. Now, here is the JavaScript code:
export class CharField extends Component {
get formattedValue() {
return formatChar(this.props.value, { isPassword: this.props.isPassword });
}
updateValue(ev) {
let value = ev.target.value;
if (this.props.shouldTrim) {
value = value.trim();
}
this.props.update(value);
}
}
CharField.template = "web.CharField";
CharField.displayName = _lt("Text");
CharField.supportedTypes = ["char"];
CharField.extractProps = ({ attrs, field }) => {
return {
shouldTrim: field.trim && !archParseBoolean(attrs.password),
maxLength: field.size,
isPassword: archParseBoolean(attrs.password),
placeholder: attrs.placeholder,
};
};
registry.category("fields").add("char", CharField);
There are a few important things to notice:
The
CharField
receives its (raw) value in props. It needs to format it before displaying it.It receives an
update
function in its props, which is used by the field to notify the owner of the state that the value of this field has been changed. Note that the field does not (and should not) maintain a local state with its value. Whenever the change has been applied, it will come back (possibly after an onchange) by the way of the props.It defines an
extractProps
function. This is a step that translates generic standard props, specific to a view, to specialized props, useful to the component. This allows the component to have a better API, and may make it so that it is reusable.
Fields have to be registered in the fields
registry. Once it’s done, they can be used in some
views (namely: form
, list
, kanban
) by using the widget
attribute.
Example
<field name="preview_moves" widget="account_resequence_widget"/>
Goal
The solutions for each exercise of the chapter are hosted on the official Flectra tutorials repository.
1. An image_preview
field¶
Each new order on the website will be created as an awesome_tshirt.order
. This model has a
image_url
field (of type char
), which is currently only visible as a string. We want to be able
to see it in the form view.
For this task, we need to create a new field component image_preview
. This component is
specified as follows: In readonly mode, it is only an image tag with the correct src
if the field
is set; In edit mode, it also behaves like classical char
fields (you can use the CharField
in
your template by passing it in the props). An input
should be displayed with the text value of the
field, so it can be edited.
Exercise
Create a new
ImagePreview
component and use theCharField
component in your template. You can use t-props to pass props received byImagePreview
toCharField
.Register your field in the proper registry.
Update the arch of the form view to use your new field by setting the
widget
attribute.
Note
It is possible to solve this exercise by inheriting CharField
, but the goal of this
exercise is to create a field from scratch.
See also
2. Improving the image_preview
field¶
Exercise
We want to improve the field of the previous task to help the staff recognize orders for which some action should be done. In particular, we want to display a warning “MISSING TSHIRT DESIGN” in red if there is no image URL specified on the order.
3. Customizing a field component¶
Let’s see how to use inheritance to extend an existing component.
There is a is_late
, readonly, boolean field on the task model. That would be useful information to
see on the list/kanban/view. Then, let us say that we want to add a red word “Late!” next to it
whenever it is set to true.
Exercise
Create a new
LateOrderBoolean
field inheriting fromBooleanField
. The template ofLateOrderBoolean
can also inherit from theBooleanField
template.Use it in the list/kanban/form view.
Modify it to add a red
Late
next to it, as requested.
4. Message for some customers¶
Flectra form views support a widget
API, which is like a field, but more generic. It is useful to
insert arbitrary components in the form view. Let us see how we can use it.
Exercise
For a super efficient workflow, we would like to display a message/warning box with some information in the form view, with specific messages depending on some conditions:
If the
image_url
field is not set, it should display “No image”.If the amount of the order is higher than 100 euros, it should display “Add promotional material”.
Make sure that your widget is updated in real time.
5. Use markup
¶
Let’s see how we can display raw HTML in a template. Before, there was a t-raw
directive that
would just output anything as HTML. This was unsafe, and has been replaced by a t-out directive that acts like a t-esc
unless
the data has been marked explicitly with a markup
function.
Exercise
Modify the previous exercise to put the
image
andmaterial
words in bold.The warnings should be markuped, and the template should be modified to use
t-out
.
Note
This is an example of a safe use of t-out
, since the string is static.
7. Auto-reload the kanban view¶
Bafien is upset: he wants to see the kanban view of the tshirt orders on his external monitor, but the view needs to be up-to-date. He is tired of clicking on the refresh icon every 30s, so he tasked you to find a way to do it automatically.
Just like the previous exercise, that kind of customization requires creating a new JavaScript view.
Exercise
Extend the kanban view/controller to reload its data every minute.
Register it in the view registry, under
awesome_tshirt.autoreloadkanban
.Use it in the arch of the kanban view (with the
js_class
attribute).
Important
If you use setInterval
or something similar, make sure that it is properly canceled when your
component is unmounted. Otherwise, you will introduce a memory leak.