Odoo Mengubah Widget Javascript

Odoo memiliki banyak widget yang siap dipakai, seperti many2many_tags, image, html, handle dll. Penggunaanya pun cukup mudah. Tapi dari semua widget yang dimiliki Odoo menurut saya many2many_tags ini sedikit aneh. Kenapa ? Karena tidak bisa diklik.

Maksud saya jika diklik tidak diarahkan ke halaman lain, tidak seperti saudaranya many2one. Pada artikel ini saya akan berbagi bagaimana mengubah widget Odoo, lebih tepatnya mengubah widget many2many_tags agar bisa diklik seperti many2one.

Dimana source code widget ?

Widget biasanya ditulis dalam bentuk file javascript dan xml di module web. File javasscript widget many2many_tags ditulis di /web/static/src/js/fields/relational_fields.js. Sedangkan file xml atau templatenya berada di /web/static/src/xml/base.xml.

Template

Template adalah file xml yang dirender jika widget dijalankan. Untuk memodifikasi widget many2many_tags kita harus buat template terlebih dahulu. Buat file xml dengan nama template.xml atau terserah anda di folder module_anda/static/src/xml dan copy paste kode dibawah ini.

<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
    <t t-name="FieldMany2ManyTagsLink">
        <t t-foreach="elements" t-as="el">
            <t t-set="color" t-value="el[colorField] || 0"/>
            <t t-set="colornames" t-value="['No color', 'Red', 'Orange', 'Yellow', 'Light blue', 'Dark purple', 'Salmon pink', 'Medium blue', 'Dark blue', 'Fushia', 'Green', 'Purple']"/>
            <div t-attf-class="badge badge-pill dropdown o_tag_color_#{color}" t-att-data-color="color" t-att-data-index="el_index" t-att-data-id="el.id" t-attf-title="Tag color: #{colornames[color]}">
                <t t-set="_badge_text">
                    <a href="#" class="o_external_link" t-att-modelid="el.id">
                        <span class="o_badge_text" t-att-title="el.display_name" ><span role="img" t-attf-aria-label="Tag color: #{colornames[color]}"/><t t-esc="el.display_name"/></span>
                    </a>
                </t>
                <t t-if="colorField">
                    <a href="#" class="dropdown-toggle o-no-caret" data-toggle="dropdown">
                        <t t-raw="_badge_text"/>
                    </a>
                </t>
                <t t-else="">
                    <t t-raw="_badge_text"/>
                </t>
                <a t-if="!readonly" href="#" class="fa fa-times o_delete" title="Delete" aria-label="Delete"></a>
            </div>
        </t>
    </t>
</templates>

Kode diatas sebenarnya tidak jauh berbeda dengan template asli many2many_tags, hanya saya ubah namanya jadi FieldMany2ManyTagsLink , menambah class o_external_link sebagai trigger jika diklik, dan menambah attribute modelid untuk menyimpan primary key dari model terkait.

Selanjutnya buat file javascript di module_anda/static/src/js/ dengan nama bebas seperti widget.js

Define Module

Module javascript sebaiknya anda define dulu dengan memanggil kode seperti dibawah ini.

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

    // letakkan kode anda disini

});

Perhatikan parameter pertama pada function define diatas. Rumusnya adalah nama_module_anda.teks_bebas. Maksud kode diatas adalah agar module yang anda tulis mudah jika ingin di-override oleh module lain, dan agar kode anda urutan dijalankan-nya oleh odoo tepat. Lihat bagian selanjutnya.

Dependensi

Depedensi ini seperti fungsi import di python. Untuk mengubah fungsi widget many2many_tags paling tidak kita harus meng-import beberapa module javascript seperti dibawah ini.

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

    var core = require('web.core');
    var AbstractField = require('web.AbstractField');
    var registry = require('web.field_registry');
    var relational_fields = require('web.relational_fields');

});

Dari kode diatas kode anda tidak akan diload oleh Odoo sebelum kode web.core, web.AbstractField dll selesai diload. Inilah depedensi di Odoo.

Perhatian variabel relational_fields. Jika anda perhatikan web.relational_fields adalah kode yang ditulis di file /web/static/src/js/fields/relational_fields.js. Jadi pada Odoo depedensi tidak ditulis berdasarkan di file mana kode ditulis. Tapi pada teks apa yang anda masukkan sebagai parameter di function odoo.define. Lebih tepatnya untuk meng-import javascript module odoo kita tidak harus menulis lengkap nama file dan foldernya.

Include atau Extend

Include digunakan jika kita ingin mengubah fungsi suatu widget disemua tempat, atau bisa disebut juga overriding method super. Sedangkan extend sama dengan inheritance, kita bisa menentukan dimana saja perubahan ini diterapkan secara manual. Karena saya tidak ingin semua tampilan yang menggunakan widget many2many_tags bisa di klik di semua tampilan, maka saya akan menggunakan extend, agar saya bisa menentukan mana tampilan widget many2many_tags yang bisa di klik dan mana yang tidak. Perhatikan kode dibawah.

// define module baru dengan rumus nama_module.teks_bebas_atau_nama_file
odoo.define('many2many_tags_link.widget', function (require) {
"use strict";
    
    // load dependensi yang dibutuhkan, anggap saja sama dengan fungsi import di python
    var core = require('web.core');
    var AbstractField = require('web.AbstractField');
    var registry = require('web.field_registry');
    var relational_fields = require('web.relational_fields');

    var _t = core._t;
    var qweb = core.qweb;

    // mulai override module relational_fields dengan memanggil fungsi include atau extend
    // variabel relational_fields ini memiliki banyak objeck, jika perlu coba console.log
    // pada kode ini kita coba overide object FieldMany2ManyTags 
    // jika ingin menggunakan fungsi include dimana perubahan terjadi di semua tempat, gunakan kode ini

    // var FieldMany2ManyTagsLink = relational_fields.FieldMany2ManyTags.include

    // disini kita menggunakan fungsi extend karena kita ingin perubahan terjadi pada tempat tertentu saja

    var FieldMany2ManyTagsLink = relational_fields.FieldMany2ManyTags.extend({
        tag_template: "FieldMany2ManyTagsLink", // panggil template / file xml yang sudah kita tulis
        events: _.extend({}, AbstractField.prototype.events, { // ini adalah daftar event / action 
            'click .o_delete': '_onDeleteTag', // ini bawaan odoo
            'click .o_external_link': '_openRelated', // ini custom, untuk menghandle jika widget diklik akan memanggil fungsi _openRelated
        }),
        _openRelated: function (event) { 
            // aslinya nyontoh dari function _onClick object FieldMany2One
            // di file yang sama dimana kode asli widget many2many_tag ditulis
            // lihat file /web/static/src/js/fields/relational_fields.js
            event.preventDefault();
            event.stopPropagation();
            var self = this;
            
            var modelid = parseInt(event.currentTarget.getAttribute('modelid'));   

            if (this.mode === 'readonly' && !this.noOpen && modelid) {              
                this._rpc({
                        model: this.field.relation,
                        method: 'get_formview_action',
                        args: [[modelid]],
                        context: this.record.getContext(this.recordParams),
                    })
                    .then(function (action) {
                        self.trigger_up('do_action', {action: action});
                    });
            }
        },    

    });

    // kode ini ditulis agar widget yang kita buat bisa dipanggil dengan cara menulis
    // <field name="sales_person_ids" widget="many2many_tags_link"/>
    // di file xml erp
    // jika menggunakan fungsi extend dan kode ini tidak ditulis, widget tidak bisa digunakan

    registry
    .add('many2many_tags_link', FieldMany2ManyTagsLink);

    // kode ini ditulis agar widget yang kita tulis bisa dijadikan depedensi oleh module lain dan dapat diverride
    // widget tetap jalan jika kode ini tidak ditulis

    return {
        FieldMany2ManyTagsLink: FieldMany2ManyTagsLink,
    }

});

Terkahir, silakan load file javascript dan xml yang sudah anda buat. Lebih detailnya silakan download module lengkapnya disini dan perhatikan file manifest.py dan views/view.xml.

Artikel ini ditulis berdasarkan odoo versi 12.

Tulisan Serupa

Leave a Reply

Your email address will not be published. Required fields are marked *