Pemrograman Javascript pada Odoo (Bagian Tiga) – Event Jquery

Artikel ini adalah bagian ketiga dari seri pemrograman javascript pada odoo. Jika anda belum membaca artikel bagian pertama atau kedua, saya sarankan untuk membaca kedua artikel tersebut terlebih dahulu. Linknya seharusnya bisa anda temukan di bagian bawah halaman ini.

Pada bagian kedua kita telah membahas bagaimana menambah event click pada widget, serta bagaimana mengubah value dari field tersebut. Pada bagian ketiga ini, kita akan membahas bagaimana menulis event jquery, mendapatkan value dari field/widget lain, dan bagaimana mengubah value dari field/widget lain yang masih satu halaman.

Pertama mari kita tambah sebuah tombol lagi pada widget yang telah kita buat di artikel bagian kedua.

<?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="formated_value" disabled="disabled" />
                    <div class="input-group-append">
                        <button class="btn btn-success btn-plus"> + </button>
                        <!-- Tombol tambahan di tutorial bagian ketiga -->
                        <button class="btn btn-primary btn-copy"><i class="fa fa-copy"></i></button>
                    </div>
                </div>
            </t>
            <t t-if="widget.mode == 'readonly' ">
                <span t-esc="formated_value" />
            </t>
        </div>
    </t>

</template>

Tampilannya kira-kira akan jadi seperti ini.

Tambah tombol pada widget odoo

Kita bisa menulis kode jquery di method apapun, bahkan diluar widget, akan tetapi jika kita ingin mengakses element dari widget yang kita buat, pastikan template telah dirender, misal dibagian paling bawah method _render.

Saat menulis event jquery, misal event click pada tombol dengan class btn-copy seperti pada kode diatas, saya tidak menyarankan menggunakan kode $(‘.btn-copy’).click() seperti pada kode di bawah ini.

_render: function () {
    // render ulang jika nilai dari field berubah
    // format value agar tampilannya ada pemisah ribuan
    var formated_value = field_utils.format[this.formatType](this.value);
    this.$el.html($(qweb.render(this.template, {'widget': this, 'formated_value': formated_value})));
    $('.btn-copy').click(function(){
        alert('click copy button');
    });
},

Kenapa ? Karena dari pengalaman saya, tidak semua element bisa ditambah event dengan kode di atas. Bukan berarti kode $(element).click() tidak bisa digunakan, karena kode dibawah ini akan dieksekusi dengan baik-baik saja.

_render: function () {
    // render ulang jika nilai dari field berubah
    // format value agar tampilannya ada pemisah ribuan
    var formated_value = field_utils.format[this.formatType](this.value);
    this.$el.html($(qweb.render(this.template, {'widget': this, 'formated_value': formated_value})));
    $('.o_form_button_save').click(function(){
        alert('click save button');
    });
},

Dengan kode di atas, saat anda melakukan click pada tombol Save, pesan click save button akan ditampilkan.

Cara terbaik untuk menambah event jquery pada widget adalah dengan menggunakan kode this.$el.find(element).click(), seperti pada kode dibawah ini.

_render: function () {
    // render ulang jika nilai dari field berubah
    // format value agar tampilannya ada pemisah ribuan
    var formated_value = field_utils.format[this.formatType](this.value);
    this.$el.html($(qweb.render(this.template, {'widget': this, 'formated_value': formated_value})));
    this.$el.find('.btn-copy').click(function(){
        alert('click on copy button');
    });
},

Dengan kode this.$el.find(element) odoo akan memastikan bahwa event click di atas hanya akan dieksekusi pada satu view/field saja. Saya menyarankan untuk selalu menggunakan kode this.$el.find(element) jika anda ingin menulis event dengan jquery, atau untuk mendapatkan value dari element dalam widget. Untuk jaga-jaga jika widget yang kita buat dipakai lebih dari satu field pada satu form, atau ada widget lain yang menggunakan class yang sama. Tentu tidak lucu jika event yang kita tulis malah mengeksekusi aksi dari widget lain.

Selanjutnya bagaimana jika kita ingin mengakses value dari field lain ?

Sebagai contoh kasus mari kita tambah 2 buah field integer lagi di form yang telah kita buat, sehingga tampilannya akan jadi seperti gambar di bawah ini.

Menambah field pada odoo

Kemudian pada event click jquery yang telah kita buat, tambahkan perintah console.log seperti pada kode di bawah ini.

_render: function () {
    // render ulang jika nilai dari field berubah
    // format value agar tampilannya ada pemisah ribuan
    var self = this;
    var formated_value = field_utils.format[this.formatType](this.value);
    this.$el.html($(qweb.render(this.template, {'widget': this, 'formated_value': formated_value})));
    this.$el.find('.btn-copy').click(function(){
        console.log(self);
    });
},

PENTING !!! Saat kita menulis event jquery kemudian diikuti dengan anonymous function usahkan untuk menyimpan nilai dari widget pada sebuah variabel temporary, pada contoh kode di atas saya menyimpan nilai widget saat ini ke dalam sebuah variabel dengan nama self, karena di dalam anonymous function, variabel this sudah tidak lagi mengarah ke widget yang kita buat, tapi pada element yang kita tambah event yaitu tombol dengan class btn-copy.

Restart service odoo, kemudian refresh browser anda. Pada mode edit, klik tombol copy kemudian perhatikan tab console di developer tools.

Nilai widget odoo di console log

Untuk mendapatkan nilai dari suatu field pada suatu form, kita bisa melihatnya di property recordData atau record seperti pada gambar di atas. Pada gambar di atas nilai dari Field Two dan Field Three masih 0, sekarang mari kita ubah nilai kedua field di atas kemudian klik tombol copy lagi.

Nilai widget odoo di console log

Pada user interface nilai Field Two dan Field Three sudah berubah, tetapi di console nilainya masih 0. Ok. Sekarang mari kita klik tombol + atau kemudian kita klik tombol copy lagi.

Nilai widget odoo di console log

Sekarang nilai dari Field Two dan Field Three di console sudah sama dengan nilai field tersebut di user interface.

Selanjutnya mari kita test dengan memindah kode console.log di atas di method lain, misal saat user klik tombol + seperti pada kode di bawah ini.

btn_plus_action: function(){
    console.log(this);
    var new_value = this.value + this.step;
    this._setValue(new_value.toString());
},

Seharusnya di console nilai semua field sudah sama persis dengan nilai yang tampil di user interface. Selanjutnya coba hapus atau comment kode this._setValue(new_value.toString()); di atas. Apakah nilai semua field di console sudah sama dengan nilai di user interface ? 🙂 Memang untuk mendapatkan nilai suatu field dengan mengakses object this/self ini agak tricky. Tetapi, tergantung dari type suatu field, kadang kita masih bisa memanfaatkan jquery. Coba inspect element input Field Two kemudian perhatikan attribute element tersebut.

Nilai widget odoo di console log

Dari gambar di atas, element input suatu field integer memiliki attribute name dengan value yang sama dengan nama field tersebut. Sehingga kita bisa mengakses nilai dari field tersebut dengan kode jquery seperti ini.

_render: function () {
    // render ulang jika nilai dari field berubah
    // format value agar tampilannya ada pemisah ribuan
    var self = this;
    var formated_value = field_utils.format[this.formatType](this.value);
    this.$el.html($(qweb.render(this.template, {'widget': this, 'formated_value': formated_value})));
    this.$el.find('.btn-copy').click(function(){
        var field_two_val = $('[name=field_two]').val();
        console.log(field_two_val);
    });
},

Lalu bagaimana jika kita ingin mengubah value field lain dengan javascript ?

Untuk mengubah value field lain kita tidak bisa mengubahnya langsung pada object recordData, seperti pada kode self.recordData.field_three = 3000;, melainkan harus memanggil method self.trigger_up(‘field_changed’,values) seperti pada kode di bawah ini.

_render: function () {
    // render ulang jika nilai dari field berubah
    // format value agar tampilannya ada pemisah ribuan
    var self = this;
    var formated_value = field_utils.format[this.formatType](this.value);
    this.$el.html($(qweb.render(this.template, {'widget': this, 'formated_value': formated_value})));
    this.$el.find('.btn-copy').click(function(){
    	// kita juga bisa menggunakan kode
        // self.$el.find('input').val();
        // jika kita ingin mendapatkan value dari field one menggunakan jquery
        // dengan cara mengakses element widget
        var field_one_val = self.value;
        var field_two_val = $('[name=field_two]').val();
        var field_three_val = field_one_val + parseInt(field_two_val);
        self.trigger_up('field_changed', {
            dataPointID: self.dataPointID,
            viewType: self.viewType,
            changes: {'field_three': field_three_val},
        });
    });
},

Abaikan variabel dataPointID, tulis langsung begitu saja, variabel ini biasanya berisi informasi nama model dan sebuah integer, saya tidak tahu dari mana integer ini diperoleh dan apa kegunaanya. Sedangkan variabel viewType adalah type view dimana widget kita dipakai, biasanya adalah form atau tree.

Yang harus anda perhatikan adalah variabel changes yang harus berupa object dengan key adalah nama field lain yang ingin anda ubah nilainya, sedangkan valuenya tergantung dari type field tersebut. Karena pada tutorial ini type field field_three adalah integer, maka nilai yang harus dimasukkan harus berupa number.

Demikian akhir dari artikel bagian ketiga ini. Jika tidak ada halangan saya akan lebih menyarankan anda untuk menulis event seperti yang kita lakukan pada artikel bagian kedua. Sedangkan untuk mengubah nilai dari field lain, saya akan lebih menyarankan anda untuk mengugunakan decorator @api.onchange dengan python.

Download Source Code
Tulisan Serupa

Leave a Reply