Sebagai aplikasi berbasis web, bagi programmer yang sudah mengerjakan aplikasi web sebelumnya, odoo kadang terasa aneh. Karena kita jarang sekali melakukan pemrograman dengan bahasa javascript. Hampir semua logic ditulis di backend dalam bahasa python, kecuali saat melakukan kustomisasi module point of sale atau e-commerce.
Bagi anda yang mulai belajar kustomisasi module odoo, pemrograman dengan bahasa javascript seharusnya menjadi bagian terakhir yang anda pelajari. Lebih baik fokus belajar bahasa pemrograman python dan bagaimana menulis model pada odoo. Kecuali tugas pertama anda adalah kustomisasi module point of sale dan ecommerce tadi.
Ada 3 area penggunaan javascript pada odoo, yaitu backend, point of sale dan frontend (website atau ecommerce). Tutorial ini akan saya bagi dalam beberapa bagian untuk meng-cover penggunaan javascript di 3 area tadi.
NOTE !!! Tutorial ini ditulis untuk odoo 14. Ada kemungkinan tidak berjalan semestinya di odoo versi yang lain.
Tidak banyak skill yang dibutuhkan untuk melakukan pemrograman javascript pada odoo, cukup pengetahuan dasar javascript dan jquery. Umumnya kode javascript odoo ditulis di module web lebih tepatnya pada directory web/static/src/js/. Silakan lihat-lihat isi directory tersebut di halaman github odoo.
Pada bagian pertama pada seri tutorial pemrograman javascript odoo ini, saya akan membahas bagaimana membuat widget. Widget adalah bagian odoo yang digunakan untuk merender value suatu field. Misal pada field Many2many secara default akan ditampilkan dalam bentuk table, tetapi jika kita menggunakan widget many2many_tags value dari field tersebut akan ditampilkan dalam bentuk chip atau badge.
Contoh widget lain adalah widget image, yang digunakan untuk menampilkan gambar pada master product.
Untuk membuat widget kita harus me-load file javascript terlebih dahulu. Pertama buat file js, dengan nama misal widget_one.js. Letakkan file ini di directory nama_module_anda/static/src/js/. Sebelum menulis kode widget sebaiknya kita tes apakah file widget_one.js berhasil di load oleh odoo atau tidak, dengan menulis kode console log seperti dibawah ini.
console.log('hello world !');
Selanjutnya untuk me-load file javascript kita harus membuat sebuah file xml, umumnya nama filenya adalah assets.xml yang diletakkan di directory view, tetapi kita juga bisa menggunakan nama lain. Pada file xml ini buat template yang inherit ke template web.assets_backend, kemudian tulis kode untuk me-load file javascript widget_one.js yang sudah kita buat sebelumnya. Seperti pada kode dibawah ini.
<?xml version="1.0" encoding="utf-8"?> <odoo> <data> <template id="tutorial_javascript_assets_backend" inherit_id="web.assets_backend" name="assets backend"> <xpath expr="script[last()]" position="after"> <script type="text/javascript" src="/tutorial_javascript/static/src/js/widget_one.js"/> </xpath> </template> </data> </odoo>
Saat anda membuat template untuk me-load file javascript, pada kode di atas perhatikan bagian inherit_id=”web.assets_backend”. Jika kita inherit ke template web.assets_backend odoo akan meletakkan file javascript kita di backend/erp. Oleh karena itu kode yang kita tulis tidak akan berjalan di point of sale atau e-commerce.
Kode yang digunakan untuk me-load file javascript sama dengan kode html pada umumnya, yaitu tag script. Yang perlu diperhatikan adalah pada bagian attribute src. Pada attribute ini kita harus menulis path dimana file disimpan dengan lengkap, termasuk nama module. Pada tutorial ini nama module saya adalah tutorial_javascript.
Selanjutnya load file xml tadi di file __manifest__.py, restart service odoo, kemudian install module. Saat kita refresh browser, jika file javascript yang kita buat berhasil di-load oleh odoo, seharusnya pesannya akan tampil di console, seperti gambar dibawah ini.
Selanjutnya pada file widget_one.js panggil function odoo.define dengan argument pertama adalah sebuah string. String ini fungsinya adalah sebagai penanda agar widget yang kita tulis bisa di extend atau di override oleh module lain. String ini harus unik, oleh karena itu biasanya format penulisannya adalah nama module diikuti text bebas.
Argument kedua adalah sebuah function, didalam function inilah kode widget kita ditulis.
odoo.define('tutorial_javascript.widget_one', function (require) { "use strict"; console.log('kode widget diletakkan disini'); });
Semua widget harus extend ke object AbstractField atau object turunannya. Juga harus ditambahkan kedalam object field_registry. Jadi mari kita import kedua object tersebut terlebih dahulu.
odoo.define('tutorial_javascript.widget_one', function (require) { "use strict"; var AbstractField = require('web.AbstractField'); var FieldRegistry = require('web.field_registry'); });
Saat membuat widget usahakan untuk selalu masuk ke mode debug, dan aktifkan developer tools, untuk mengetahui jika ada error. Berikut ini adalah contoh gambar yang menampilkan pesan error odoo saat kita membuat widget.
Pesan error di atas terjadi karena object web.AbstractFields tidak ditemukan karena kesalahan penulisan, seharusnya object yang benar adalah web.AbstractField tanpa ‘s’ di akhir nama object.
Pada tutorial ini kita akan membuat sebuah widget yang sederhana saja, misal untuk menampilkan sebuah pesan singkat. Tampilan sebuah widget bisa digenerate lewat sebuah template dalam format xml, atau lewat kode javascript dengan meng-override method _render, _renderEdit, atau _renderReadonly. Kali ini kita akan membuat tampilan sebuah widget dengan template, sedangkan tampilan dengan kode javascript akan kita bahas di lain waktu jika ada kesempatan.
Untuk membuat sebuah template, buat sebuah file xml kemudian tulis kode seperti kode di bawah ini.
<?xml version="1.0" encoding="UTF-8"?> <template> <t t-name="WidgetOneTemplate"> <div> <t t-if="widget.mode == 'edit' "> <p>Ini adalah tampilan widget saat mode edit (user sedang mengedit dokumen)</p> </t> <t t-if="widget.mode == 'readonly' "> <p>Ini adalah tampilan widget saat mode readonly (user hanya lihat dokumen)</p> </t> </div> </t> </template>
Sebuah widget memiliki 2 mode, yaitu mode edit dimana user sedang menekan tombol Create atau tombol Edit, sehingga dia bisa mengubah isi dokumen. Dan mode readonly yaitu mode dimana user hanya bisa lihat saja. Jadi kita harus menyiapkan 2 buah view/tampilan yang berbeda untuk kedua mode ini.
Selanjutnya simpan file xml di atas di directory nama_module_anda/static/src/xml. Dan jangan lupa untuk menambahkannya di file __manifest__.py.
Kira-kira struktur directory module yang kita buat dan isi file __manifest__.py akan terlihat seperti di bawah ini.
Selanjutnya kita tinggal menulis kode widget yang sebenarnya. Silakan baca kode di bawah ini dan perhatikan pada bagian komentar.
odoo.define('tutorial_javascript.widget_one', function (require) { "use strict"; // import object yang dibutuhkan untuk membuat sebuah widget var AbstractField = require('web.AbstractField'); var FieldRegistry = require('web.field_registry'); // buat sebuah object dengan nama bebas // jangan lupa untuk extend ke object web.AbstractField atau object turunanya var WidgetOne = AbstractField.extend({ template: 'WidgetOneTemplate', // isi nama template yang telah dibuat untuk mengatur tampilan/view widget }); // daftarkan widget yang telah kita buat ke web.field_registry // agar kita bisa menggunakan widget yang kita buat di file xml/view odoo // dengan kode seperti di bawah ini // <field name="field_one" widget="widget_one" /> // nama 'widget_one' ini bebas, asal selalu nyambung/tanpa spasi FieldRegistry.add('widget_one', WidgetOne); // return object widget yang telah kita buat // agar bisa di-extend atau di-override oleh module lain return WidgetOne; });
Selanjutnya kita bisa langsung menggunakan widget yang telah kita buat di file xml/view odoo dengan menggunakan kode seperti di bawah ini.
<record id="tutorial_javascript_form" model="ir.ui.view"> <field name="name">tutorial.javascript.form</field> <field name="model">tutorial.javascript</field> <field name="arch" type="xml"> <form> <sheet> <group> <field name="field_one" widget="widget_one" /> </group> </sheet> </form> </field> </record>
Jika kode anda tidak error tampilannya kira-kira akan jadi seperti ini.
Pada mode edit template widget akan selalu tampil. Tetapi pada mode readonly jika nilai dari field yang menggunakan widget yang telah kita buat bernilai null tampilannya akan blank. Jadi pastikan untuk mengisi nilai field tersebut agar contoh tampilan pada mode readonly pada tutorial ini bisa terlihat. Anda bisa mengubahnya lewat database atau memberi nilai default pada field tersebut seperti pada kode di bawah ini.
field_one = fields.Integer('Field One', default=1)
Perlu anda ingat saat anda mengedit file di directory static dalam hal ini termasuk file js, css, dan xml anda tidak perlu untuk meng-upgrade module yang anda buat. Cukup restart service odoo anda dan refresh browser.
Demikian tutorial pemrograman javascript pada odoo bagian pertama ini. Semoga bermanfaat bagi anda.
Download Source Code
4 Replies to “Pemrograman Javascript pada Odoo (Bagian Satu) – Tampilan Widget”
Assalamualaikum. Selamat Siang
sblmnya sy tidak bisa javascript, saya masih bingung kapan harus pakai AbstractField, Core dst. Sy sudah coba baca tapi masih belum paham urutan javascript odoo jalan, dia manggil apa aja dluan jadi saya pun masih blum paham algoritmanya. atau mungkin pola berfikirnya frontend beda kali ya.
ini contohnya kan nambahin field yah. Bisa minta tulung kasih saran atau tutorial kalau saya mau bikin widget Button
nah sy mau coba bikin button, yg mana jika dipanggil bisa mengeluarkan data dari form yg mnggunakan widget itu, misalnya berupa alert tapi informasinya dari form itu. ini wajib di client side. jadi ga bisa pakai backend
Terimakasih
Kalau mau menampilkan alert dari button tidak perlu javascript. Cukup di python raise exception jika hanya sekedar ingin menampilkan pesan saja. Atau return ir.actions.act_window jika ingin menampilkan alert yang lebih kompleks, misal sambil isi form dll. Di odoo 14 silakan lihat kode waktu cancel sales order jika sudah punya invoice dengan status draft. Misal di baris 805 ini .
Kak izin bertanya klo mau load field ke POS Web Receipt itu gimana ya? Misal field itu dari model lain lalu kita ingin load yg id-nya sesuai/berelasi dgn id pos.order saat ini. Saya coba2 pusing, mungkin bisa dibuatkan postingan khusus mengenai masalah ini. Terima kasih.
1. Nilai yang mau dirender harus dimasukkan ke method get_receipt_render_env atau method lain yang dipanggil oleh method ini, misal method export_for_printing dari model Order atau yang lainnya.
2. Lalu render nilai tersebut di template OrderReceipt.
3. Screen POS tidak menyimpan id pos.order, tapi pos.order menyimpan nama order “order.get_name() kalau di javascript” di field pos_reference. jadi lakukan ajax request ke server berdasarkan field tersebut kalau data yang mau dirender tidak ada di javascript dan harus ambil dari server.
4. Modif source code odoo aja langsung, tanpa buat module dulu, kalau sudah berhasil baru cari tahu cara pindah perubahan itu ke module terpisah.
NOTE: link di atas mengacu pada odoo 13