odoo官方文档第十一章 Javascript Cheatsheet

Javascript Cheatsheet

有许多方法可以解决JavaScript和Odoo中的问题。 但是,Odoo框架被设计为可扩展(这是一个非常大的约束),并且一些常见问题有一个很好的标准解决方案。 标准解决方案可能具有易于理解的odoo开发人员的优势,并且可能会在修改Odoo时继续工作。

本文档试图解释解决其中一些问题的方法。 请注意,这不是参考。 这只是一个随机的菜单集合,或者在某些情况下如何处理的解释。

首先,请记住,使用JS自定义odoo的第一条规则是:尝试在python中执行此操作。 这可能看起来很奇怪,但是python框架是可扩展的,并且可以通过轻触xml或python来完成许多行为。 与使用JS相比,这通常具有更低的维护成本:

如果需要与服务器通信并与javascript框架正确集成,则实现自定义行为通常更加困难。 自定义代码需要复制的框架有许多小细节。 例如,响应,或更新URL,或显示数据而不闪烁。

本文档并未真正解释任何概念。 这更像是一本食谱(cookbook)。 有关更多详细信息,请参阅javascript参考页面(请参阅Javascript参考)

Creating a new field widget

这可能是一个非常常见的用例:我们希望以非常具体(可能依赖于业务)的方式在表单视图中显示一些信息。 例如,假设我们要根据某些业务条件更改文本颜色。

这可以通过三个步骤完成:

  1. 创建新窗口小部件 widget,
  2. 在字段注册表中注册它,
  3. 然后将窗口小部件 widget添加到窗体视图中的字段
  • creating a new widget(创建新窗口小部件)
    这可以通过扩展小部件来完成:
var FieldChar = require('web.basic_fields').FieldChar;

var CustomFieldChar = Fieldchar.extend({
    renderReadonly: function () {
        // implement some custom logic here
    },
});
  • registering it in the field registry(在字段注册表中注册它)
    Web客户端需要知道窗口小部件名称与其实际类之间的映射。 这是由注册表完成的:(add进行注册)
var fieldRegistry = require('web.field_registry');

fieldRegistry.add('my-custom-field', CustomFieldChar);
  • adding the widget in the form view(将窗口小部件 添加到窗体视图中的字段)
<field name="somefield" widget="my-custom-field"/>

请注意,只有表单,列表和看板视图使用此字段小部件注册表。 这些视图紧密集成,因为列表和看板视图可以显示在表单视图中。

Modifying an existing field widget

另一个用例是我们想要修改现有的字段小部件。 例如,odoo中的voip插件需要修改FieldPhone小部件,以增加在voip上轻松调用给定数字的可能性。 这是通过包含FieldPhone小部件来完成的,因此无需更改任何现有的表单视图。

Field Widgets(AbstractField的(子类)的实例)与其他所有小部件一样,因此它们可以进行猴子补丁。 这看起来像这样:

var basic_fields = require('web.basic_fields');
var Phone = basic_fields.FieldPhone;

Phone.include({
    events: _.extend({}, Phone.prototype.events, {
        'click': '_onClick',
    }),

    _onClick: function (e) {
        if (this.mode === 'readonly') {
            e.preventDefault();
            var phoneNumber = this.value;
            // call the number on voip...
        }
    },
});

请注意,无需将小部件添加到注册表,因为它已经注册。

Modifying a main widget from the interface(从界面修改主窗口小部件)

另一个常见用例是需要从用户界面自定义一些元素。 例如,在主菜单中添加消息。 在这种情况下,通常的过程是再次包含小部件。 这是唯一的方法,因为这些小部件没有注册表。

这通常使用如下代码完成:

var AppSwitcher = require('web_enterprise.AppSwitcher');

AppSwitcher.include({
    render: function () {
        this._super();
        // do something else here...
    },
});

Adding a client action

客户端操作是一个小部件,它将控制菜单栏下方的屏幕部分。 如有必要,它可以有一个控制面板。 定义客户端操作可以分两步完成:实现新窗口小部件,并在操作注册表中注册窗口小部件。

  • Implementing a new client action:
    这是通过创建一个小部件来完成的:
var ControlPanelMixin = require('web.ControlPanelMixin');
var Widget = require('web.Widget');

var ClientAction = Widget.extend(ControlPanelMixin, {
    ...
});

如果您不需要,请不要添加控制面板mixin。 请注意,需要一些代码才能与控制面板交互(通过mixin给出的update_control_panel方法)。

  • Registering the client action:
    像往常一样,我们需要让Web客户端知道客户端操作和实际类之间的映射:
var core = require('web.core');

core.action_registry.add('my-custom-action', ClientAction);

然后,要在Web客户端中使用客户端操作,我们需要使用正确的tag属性创建客户端操作记录(模型ir.actions.client的记录):

<record id="my_client_action" model="ir.actions.client">
    <field name="name">Some Name</field>
    <field name="tag">my-custom-action</field>
</record>

Creating a new view (from scratch)

创建新视图是一个更高级的主题。 这个备忘单(cheatsheet) 只会突出显示可能需要完成的步骤(无特定顺序):

  • 将新视图类型添加到ir.ui.view的字段类型:
class View(models.Model):
    _inherit = 'ir.ui.view'

    type = fields.Selection(selection_add=[('map', "Map")])
  • 将新视图类型添加到ir.actions.act_window.view的字段view_mode
class ActWindowView(models.Model):
    _inherit = 'ir.actions.act_window.view'

    view_mode = fields.Selection(selection_add=[('map', "Map")])
  • creating the four main pieces which makes a view (in JavaScript):
    我们需要一个视图(AbstractView的子类,这是工厂),一个渲染器(来自AbstractRenderer),一个控制器(来自AbstractController)和一个模型(来自AbstractModel)。 我建议首先简单地扩展超类:
var AbstractController = require('web.AbstractController');
var AbstractModel = require('web.AbstractModel');
var AbstractRenderer = require('web.AbstractRenderer');
var AbstractView = require('web.AbstractView');

var MapController = AbstractController.extend({});
var MapRenderer = AbstractRenderer.extend({});
var MapModel = AbstractModel.extend({});

var MapView = AbstractView.extend({
    config: {
        Model: MapModel,
        Controller: MapController,
        Renderer: MapRenderer,
    },
});
  • adding the view to the registry:
    像往常一样,需要更新视图类型和实际类之间的映射:
var viewRegistry = require('web.view_registry');

viewRegistry.add('map', MapView);
  • implementing the four main classes:
    View类需要解析arch字段并设置其他三个类。 Renderer负责在用户界面中表示数据,Model应该与服务器通信,加载数据并处理它。 Controller在那里协调,与网络客户交谈,......

  • creating some views in the database:

<record id="customer_map_view" model="ir.ui.view">
    <field name="name">customer.map.view</field>
    <field name="model">res.partner</field>
    <field name="arch" type="xml">
        <map latitude="partner_latitude" longitude="partner_longitude">
            <field name="name"/>
        </map>
    </field>
</record>

Customizing an existing view

假设我们需要创建通用视图的自定义版本。 例如,一个看板视图,顶部有一些额外的带状(ribbon-like )小部件(显示一些特定的自定义信息)。 在这种情况下,这可以通过3个步骤完成: 1.扩展看板视图(也可能意味着扩展控制器/渲染器和/或模型),
2.然后在视图注册表中注册视图,
最后,3.使用看板arch中的视图 (具体示例是帮助台仪表板)。

  • extending a view:
    这是它的样子:
var HelpdeskDashboardRenderer = KanbanRenderer.extend({
    ...
});

var HelpdeskDashboardModel = KanbanModel.extend({
    ...
});

var HelpdeskDashboardController = KanbanController.extend({
    ...
});

var HelpdeskDashboardView = KanbanView.extend({
    config: _.extend({}, KanbanView.prototype.config, {
        Model: HelpdeskDashboardModel,
        Renderer: HelpdeskDashboardRenderer,
        Controller: HelpdeskDashboardController,
    }),
});
  • adding it to the view registry:
    像往常一样,我们需要通知Web客户端视图名称和实际类之间的映射。
var viewRegistry = require('web.view_registry');
viewRegistry.add('helpdesk_dashboard', HelpdeskDashboardView);
  • using it in an actual view:
    我们现在需要通知Web客户端特定的ir.ui.view需要使用我们的新类。 请注意,这是Web客户端特定的问题。 从服务器的角度来看,我们仍然有看板视图。 执行此操作的正确方法是在arch的根节点上使用特殊属性js_class(将在某天重命名为widget,因为这实际上不是一个好名称):
<record id="helpdesk_team_view_kanban" model="ir.ui.view" >
    ...
    <field name="arch" type="xml">
        <kanban js_class="helpdesk_dashboard">
            ...
        </kanban>
    </field>
</record>

注意:您可以更改视图解释arch结构的方式。 但是,从服务器的角度来看,这仍然是相同基本类型的视图,受到相同的规则(例如,rng验证)。 因此,您的视图仍需要具有有效的arch字段。

原文地址:https://www.cnblogs.com/myt2000/p/10997926.html