第十章 字段
与经典WC实现不同,新的WC中不再有Widget的实体概念,同样也不再有字段的实体概念,在新的WC实现中,所谓的字段实际上也是一种组件。
字段的定义
我们还是先来看OWL中字段的定义:
export class Field extends Component {
setup() {
this.FieldComponent = this.props.fieldInfo.FieldComponent;
if (!this.FieldComponent) {
const fieldType = this.props.record.fields[this.props.name].type;
this.FieldComponent = getFieldClassFromRegistry(fieldType, this.props.type);
}
}
...
由此我们可以知道,字段实际上就是一种组件。
创建字段
知道了字段的属性,那么我们如何创建一个新的字段类型呢?这里我们以微信公众号模块的升级为例,来说明如何创建一个OWL的字段。由于odoo16.0不再兼容经典的WC实现,因此我们之前版本的代码已经不能在16.0上面使用,我们需要使用OWL的方式将我们的代码升级。
首先,我们需要创建一个新的字段类型WeChatMedia:
import { registry } from '@web/core/registry';
import { standardFieldProps } from '@web/views/fields/standard_field_props';
const { Component,useRef } = owl;
export class WechatMedia extends Component {
setup(){
this.input = useRef("input");
}
...
WechatMedia.template = 'mommy_wechat_media.WechatMedia';
WechatMedia.props = {
...standardFieldProps,
}
registry.category('fields').add('wechatmedia', WechatMedia);
我们首先创建了WechatMedia这个类型的字段组件,然后设置了它的初始属性和若干业务逻辑方法(此处省略)。然后,我们指定了它的模版名称,并继承了标准字段所拥有的属性,最后将其注册到了字段注册中心。
然后我们来看模版的代码:
<t t-name="mommy_wechat_media.WechatMedia" owl="1">
<div t-if="!props.readonly">
<span class="wechat_form_field"></span>
<form id="wechatform" class="wechat_form_field_upload" enctype="multipart/form-data">
<div>
<input type="file" class="o_form_input wechat_file" t-ref="input"/>
<button class="btn btn-sm btn-primary o_select_file_button" title="Select" t-on-click="()=> this.uploadWeChat()">上传媒体文件</button>
</div>
</form>
</div>
<div t-else="">
<span t-esc="formattedValue"/>
</div>
</t>
我们根据字段是否要求只读的属性,将其显示为了两种渲染形态,如果字段没有只读属性,那么它将显示为一个文件选择按钮和一个文件上传按钮。否则,它只会显示一个静态的文本(微信媒体文件ID)。这是一个非常重要的点,我们在进行创建自己的字段的时候都要考虑到是否会设置为只读。