Odoo 自定义Widgets 基础教程(章节2)

简介:

大家好,

在上一章节的教程中,我们讲了Odoo Widget 【挂件】的基础。包括,基础方法和他们的用途。这一节,我们要做的事情,是学会如何应用这些方法到实际使用当中。

首先,我们都知道在编写odoo 的视图xml时,通过在字段中,添加 widget 标签属性即可渲染出相对应的视图。

例如: 时间挂件 ,可以将时间字段渲染成如图所示的效果。

<field name="myfield" widget="timedate"/>

image

那我们就来具体阐述一下,这个时间挂件所实现的机制和代码编写逻辑。

# 步骤一:
我们需要新建一个模块,命名它为timepicker。文件结构目录如下:【可以用scaffold先创建一个骨架,再进行修改】
image

# 步骤二:
修改 _manifest_.py,添加相关依赖。
image

# 步骤三:

我们来看看widget.js
同所有 widget 一样,第一步定义:

odoo.define('web_widget_timepicker', function (require) {
            "use strict";

 var core = require('web.core');
 //web.core是引用web包的core包
           
 var formats = require('web.formats'); 
 //引用web 包中的formats,odoo的js中预制了一部分formats,提供给大家使用

 var common = require('web.form_common');
//引用web 包中的common类,一些基础方法的引用

# 步骤四:定义widgets:

varTimeDateField = common.AbstractField.extend(common.ReinitializeFieldMixin, {

        //这里的ReinitializeFieldMixin 是最基础的挂件Mixin【其实就是类,js版本的类换汤不换药】

is_field_number: true,

//不做解释,一看就懂

template: "TimeDateField",

// 调用TimeDateField ,它被定义于 image

internal_format: 'float_time',

//不做解释,一看就懂

widget_class: 'o_form_field_time',

//此项,在模块中的/src/css里面定义
image

events: {

        'change input': 'store_dom_value', // store_dom_value 被定义在下方
    },   

//事件,是事件选择器(事件名称和由空间分隔的CSS选择器)映射到回调的方法上。回调既可以是控件中的方法名,也可以是函数。一般是指在发生事件的时候,会触发动作。
// 常见的事件还有 'click p.oe_some_class a': 'some_method',

init: function (field_manager, node) {

this._super(field_manager, node);

// field_manager是用来抓取用户输入值的方法,被定义在web.core里面。因为我们的挂件会修改此方法,将输入从原始的录入变为选填。

this.internal_set_value(0);

//如果,没有值,则设置为0

this.options = _.defaults(this.options, {
                step: 15,
                selectOnBlur: true,
                timeFormat: 'H:i',
                scrollDefault: 'now',
            });  },

// 一些基本设置,提交给jQuery用的,在initialize_content 中被调用

initialize_content: function() {
            if(!this.get("effective_readonly")) {
                this.$el.find('input').timepicker(this.options);
                this.setupFocus(this.$('input'));
            }
        },

// 初始化内容,对本实例中的el(元素)执行.timepicker方法,并带入options

is_syntax_valid: function() {
            if (!this.get("effective_readonly") && this.$("input").size() > 0) {
                try {
                    this.parse_value(this.$('input').val(), '');
                    return true;
                } catch(e) {
                    return false;
                }
            }
            return true;
        },
is_false: function() {
           return this.get('value') === '' || this._super();
       },

//检查,是否有填写错误

focus: function() {
            var input = this.$('input:first')[0];
            return input ? input.focus() : false;
        },

//焦点事件,只有当点击为焦点后才执行

set_dimensions: function (height, width) {
           this._super(height, width);
           this.$('input').css({
               height: height,
               width: width
           });
       },

//设置输入框的宽度和高度

store_dom_value: function () {
            if (!this.get('effective_readonly')) {
                this.internal_set_value(
                    this.parse_value(
                        this.$('input').val(), ''));
            }
        },

//保存用户在前端所选择的数据至数据库中

parse_value: function(val, def) {
            return formats.parse_value(val, {"widget": this.internal_format}, def);
        },

//解析填写进入的数据,在store_dom_value前会调用此方法,以免存的数据格式错误或者其他问题

format_value: function(val, def) {
            return formats.format_value(val, {"widget": this.internal_format}, def);
        },

//重新格式化内部出现的数据,在render_value 渲染数据前,需要先调用此方法,避免

render_value: function() {
  var show_value = this.format_value(this.get('value'), '');

   if (!this.get("effective_readonly")) {
                this.$input = this.$el.find('input');
                this.$input.val(show_value);
            } else {
                this.$(".o_form_time_content").text(show_value);
            }
        },
    });

//渲染最终数据

core.form_widget_registry.add('timepicker', TimeDateField);

// 将'timepicker' 注册到 widget_registry中(挂件注册表)

return {
      TimeDateField: TimeDateField,
  };
目录
相关文章
|
6月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的计算机office课程平台的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的计算机office课程平台的详细设计和实现(源码+lw+部署文档+讲解等)
|
数据处理 调度 C++
QT 学习笔记(十七)
QT 学习笔记(十七)
|
XML 数据格式
odoo 开发入门教程系列-基本视图
odoo 开发入门教程系列-基本视图
192 0
|
存储 安全 数据库
odoo 开发入门教程系列-安全-简介
odoo 开发入门教程系列-安全-简介
153 0
|
Linux
odoo 开发入门教程系列-一个新应用
odoo 开发入门教程系列-一个新应用
234 0
|
Python
odoo 开发入门教程系列-准备一些操作(Action)?
odoo 开发入门教程系列-准备一些操作(Action)?
196 0
|
XML 数据库 数据格式
odoo 开发入门教程系列-一些用户界面
odoo 开发入门教程系列-一些用户界面
379 0
Qt中文翻译(官方文档,界面,工具等)集锦
Qt中文翻译(官方文档,界面,工具等)集锦
716 0
Wix 安装部署教程(十二) -- 自动更新WXS文件
原文:Wix 安装部署教程(十二) -- 自动更新WXS文件         上一篇分享了一个QuickWIX,用来对比两个工程前后的差异,但是这样还是很繁琐,而且昨天发现有Bug,目录对比有问题。这次改变做法,完全让程序自动去更新WXS文件,然后再用CCNet去自动编译,这样的话,工程师更新文件,再也不用我去编译,发布了。
1241 0