This page looks best with JavaScript enabled

(Javascript trong Odoo) Phần 2 Tạo logic cho widget

 ·  ☕ 4 phút đọc · 👀... views

Trong phần 1, chúng ta đã tạo ra 1 Widget để hiển thị một đoạn text văn bản. Sang phần 2 này, chúng ta cùng nhau xây dựng một logic cho widget này.
Tiếp theo bạn cần khai báo 1 trường như sau:

1
field_one = fields.Integer('Field One')

Thông thường khi chúng ta khai báo 1 field như trên và thêm chúng vào XML, mặc định Odoo sẽ cho chúng ta sửa giá trị trên giao diện kiểu như sau:

Nhưng để có thể hạn chế thêm việc người dùng nhập vào không phải ký tự là số nguyên, ở đây mình sẽ thêm 2 nút tăng giảm + - và trường giá trị để readonly.
Dưới đây là đoạn code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<template>
 
    <t t-name="WidgetOneTemplate">
        <div>
            <t t-if="widget.mode == 'edit' ">
                <div class="input-group">
                    <div class="input-group-prepend">
                        <button class="btn btn-danger btn-minus"> - </button>
                    </div>
                    <input type="text" class="form-control" t-att-value="widget.value" disabled="disabled" />
                    <div class="input-group-append">
                        <button class="btn btn-success btn-plus"> + </button>
                    </div>
                </div>
            </t>
            <t t-if="widget.mode == 'readonly' ">
                <span t-esc="widget.value" />
            </t>
        </div>
    </t>
 
</template>

Trong form ở chế độ chỉnh sửa sẽ như sau:

Sau đó, ở file widget_one.js mình sẽ tiến hành thêm event với 2 button là +-, dưới đây là đoạn code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
var WidgetOne = AbstractField.extend({
    template: 'WidgetOneTemplate', // fill with the template name that will be rendered by odoo
    events: { // list of event, like jquery event
        'click .btn-minus': 'btn_minus_action',
        'click .btn-plus': 'btn_plus_action',
    },
    btn_minus_action: function(){
        var new_value = this.value - 1;
        this._setValue(new_value.toString());
        console.log(this.value);
    },
    btn_plus_action: function(){
        var new_value = this.value + 1;
        this._setValue(new_value.toString());
        console.log(this.value);
    },
});

Các odoo viết sự kiện trong js cũng gần giống như jquery chỉ có điều là hơi đảo ngược 1 chút. Đối với jquery chúng ta sẽ viết như sau:

1
$('.btn-minus.').click(btn_minus_action);

Thực tế chúng ta có thể sử dụng Jquery để thay thế cho đoạn code phía trên, tuy nhiên theo cá nhân mình thấy thì sử dụng code của Odoo sẽ dễ hiểu hơn.
Tuy nhiên nếu có cơ hội mình sẽ chia sẻ thêm về vấn đề này(cũng không phải là không có cách😄)

Để có thể thay đổi giá trị của field chúng ta có thể dùng phương thức this._setValue(new_value), nhưng chú ý kiểu dữ liệu của new_value, trong ví dụ của chúng ta
biến mà chúng ta truyền vào hàm _setValue phải là string. Thực ra mặc định không hẳn vậy, ví dụ khi chúng ta nhập giá trị vào ô input là 12345678, odoo hiểu ở đây là 1
chuỗi string và tự động chuyển sang integer để cộng trừ nhân chia.

Với đoạn code trên chúng ta cần chú ý toString(), tại sao chúng ta lại cần ép kiểu về string? Lý do mình đã giải thích bên trên, đơn giản là chúng ta cần phải ép kiểu
về như vậy

Oh, nhưng khoan đã! Tại sao giá trị field của chúng ta vẫn là 0 và không hề thay đổi.

Điều này chỉ ra rằng, khi chúng ta thực hiện thay đổi giá trị của field thì giao diện không tự động render lại.
Để có thể làm được điều này chúng ta cần phải override lại phương thức _render hoặc _renderEdit. Trong ví dụ của chúng ta, mình sẽ override lại hàm _render.

Có nhiều cách để thay đổi giao diện người dùng (mình sẽ đề cập trong 1 bài viết sớm), tuy nhiên ở đây mình sẽ dùng qweb và viết nó vào trong hàm _render như sau:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
odoo.define('tutorial_javascript.widget_one', function (require) {
"use strict";
    var AbstractField = require('web.AbstractField');
    var FieldRegistry = require('web.field_registry');
 
    var core = require('web.core');
    var qweb = core.qweb;
 
    var WidgetOne = AbstractField.extend({
        template: 'WidgetOneTemplate', 
        events: { 
            'click .btn-minus': 'btn_minus_action',
            'click .btn-plus': 'btn_plus_action',
        },
        btn_minus_action: function(){
            var new_value = this.value - 1;
            this._setValue(new_value.toString());            
        },
        btn_plus_action: function(){
            var new_value = this.value + 1;
            this._setValue(new_value.toString());
        },
        _render: function () {
            console.log(this.value);
            this.$el.html($(qweb.render(this.template, {'widget': this})));
        },
    });
 
    FieldRegistry.add('widget_one', WidgetOne);
 
    return WidgetOne;
 
});

Tham số đầu tiên mà mình truyền vào qweb.render() đó là template mà chúng ta muốn render lại, tham số thứ 2 ở đây chính là widget của chúng ta, khi thay đổi giá trị của field
,ở đây là widget do chúng ta đã viết nó trong xml như bên dưới:

Restart Odoo, refresh trình duyệt chúng ta thấy rằng mọi thứ đã chạy chính xác!

Đây là phần hai trong loạt bài Javascript trong Odoo, hy vọng bài viết sẽ giúp ích cho bạn 😀

Chia sẻ
Support the author with

Hùng Phạm
Viết bởi
Hùng Phạm
Web/Mobile Developer