Panduan Template Renderer Di simple-jpa


Plugin simple-jpa 0.4 dapat di-install dengan memberikan perintah install-plugin simple-jpa 0.4

Salah satu hal yang cukup merepotkan bagi saya selama membuat aplikasi Swing adalah membuat renderer. Untuk JTable, harus dibuat sebuah implementasi TableCellRenderer yang menampilkan dan men-format domain object. Masing-masing JTable memiliki TableCellRenderer-nya sendiri. Begitu juga dengan JComboBox dan JList, harus dibuat sebuah implementasi ListCellRenderer yang menampilkan dan men-format domain object. JComboBox dan JList yang menampung domain object yang berbeda akan memiliki implementasi ListCellRenderer yang berbeda.

Beberapa mahasiswa yang baru belajar sering kali berusaha menghindari repotnya membuat renderer dengan langsung melewatkan nilai domain object yang telah di-format dan dikonversi menjadi String ke JTable, JComboBox dan JList. Sekilas terlihat gampang, tapi hal ini menimbulkan sebuah permasalahan tersendiri, yaitu bila nilai JTable, JComboBox atau JList dipilih atau di-select, maka nilai yang dikembalikan adalah sebuah String. Mereka tetap harus bekerja keras untuk menerjemahkan String tersebut kembali menjadi domain object.

Lalu bagaimana cara gampangnya? Untuk mempermudah membuat renderer di Swing, saya memanfaatkan SimpleTemplateEngine di Groovy untuk menghasilkan sebuah renderer dengan cara yang sangat mudah dan sederhana. Renderer ini akan saya sebut sebagai template renderer.

Sebagai contoh, saya akan membuat sebuah aplikasi dengan domain model seperti yang terlihat pada gambar berikut ini:

Domain Model Sebuah Aplikasi Sederhana

Domain Model Sebuah Aplikasi Sederhana

Saya kemudian membuat sebuah proyek Groovy, memberikan perintah install-plugin diikuti dengan perintah create-simple-jpa. Setelah itu saya membuat domain class dengan perintah berikut ini:

create-domain-class Transaksi ItemTransaksi Buku Pengarang

Setelah itu, saya menambahkan atribut dan methods pada domain class yang dihasilkan sehingga isinya akan terlihat seperti berikut ini:

@DomainModel @Entity @Canonical
class Transaksi {

    @NotEmpty @Size(min=5, max=5)
    String kodeTransaksi

    @NotNull
    LocalDate tanggal

    @OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)
    List<ItemTransaksi> listItemTransaksi = []

    BigDecimal getTotal() {
        listItemTransaksi.sum { it.total }
    }
}

@DomainModel @Entity @Canonical(excludes="transaksi")
class ItemTransaksi {

    @NotNull @ManyToOne
    Buku buku

    @NotNull @Min(1l)
    Integer jumlah

    @ManyToOne
    Transaksi transaksi

    BigDecimal getTotal() {
        buku.harga * jumlah
    }

}

@DomainModel @Entity @Canonical
class Pengarang {

    @NotEmpty @Size(min=2, max=100)
    String namaDepan

    @Size(min=2, max=100)
    String namaBelakang

    @Email
    String email

    String getNamaLengkap() {
        namaDepan + " " + namaBelakang
    }

    @ManyToMany(mappedBy="listPengarang")
    List<Buku> listBuku = []

}

@DomainModel @Entity @Canonical(excludes="listPengarang")
class Buku {

    @NotNull @Size(min=9, max=13)
    String isbn

    @NotNull @Min(1l)
    BigDecimal harga

    @Min(1l)
    Short tahun

    @NotEmpty
    @ManyToMany
    List<Pengarang> listPengarang = []

}

Setelah ini, saya memberikan perintah untuk melakukan scaffolding:

generate-all * --startup-group=MainGroup

Bila saya menjalankan aplikasi dan mengisi data, saya akan memperoleh tampilan yang mirip seperti pada gambar berikut ini:

Tampilan Tabel Secara Default

Tampilan Tabel Secara Default

Pada halaman untuk mengisi Transaksi, tabel terdiri atas tiga kolom, masing-masing menampilkan kode transaksi, tanggal, dan list item transaksi. Tunggu! Kolom ketiga rasanya agak aneh, bukan? Kenapa harus menampilkan list item transaksi? Bukankah lebih baik bila menampilkan total transaksi saja? Untuk itu, saya perlu mengubah baris berikut ini pada TransaksiView.groovy:

eventTableModel(list: model.transaksiList,
  columnNames: ['Kode Transaksi', 
                'Tanggal', 
                'List Item Transaksi'],
  columnValues: ['${value.kodeTransaksi}', 
                 '${value.tanggal}', 
                 '${value.listItemTransaksi}'])

Penggunaan ekspresi pada atribut columnValues adalah apa yang sebut sebagai template renderer. Pada template tersebut, saya dapat menampilkan variabel dengan menggunakan tanda dollar ($). Satu-satunya variabel yang tersedia adalah variabel value yang berisi domain object yang hendak ditampilkan. Selain menampilkan variabel, saya juga dapat memasukkan kode program ke dalam template dengan menyertakannya dalam <% ... %>. Pada template renderer, saya dapat menggunakan fungsi berikut ini:

  • numberFormat() akan men-format sebuah nilai dengan format angka.
  • percentFormat() akan men-format sebuah nilai dengan format persen. Misalnya nilai 0.12 akan menjadi 12%.
  • currencyFormat() akan men-format sebuah nilai dengan format mata uang (memiliki tanda mata uang).
  • titleCase() akan men-format sebuah String sehingga setiap katanya selalu diawali huruf besar. Misalnya, titleCase("solid snake") akan menghasilkan "Solid Snake".

Untuk mengubah kolom ketiga untuk menampilkan total transaksi, saya mengubah kode program di atas menjadi seperti berikut ini:

eventTableModel(list: model.transaksiList,
  columnNames: ['Kode Transaksi', 
                'Tanggal', 
                'Total'],
  columnValues: ['${value.kodeTransaksi}', 
                 '${value.tanggal}', 
                 '${currencyFormat(value.total)}'])

Tampilan setelah perubahan akan terlihat seperti pada gambar berikut ini:

Tampilan Tabel Setelah Perubahan Template Renderer

Tampilan Tabel Setelah Perubahan Template Renderer

Terlihat bahwa dengan template renderer, saya tidak perlu repot-repot membuat sebuah class TableCellRenderer lagi.

Saya juga bisa memberikan ekspresi yang lebih rumit lagi di template renderer, misalnya seperti berikut ini:

eventTableModel(list: model.transaksiList,
  columnNames: ['Kode Transaksi', 
                'Tanggal', 
                'Total'],
  columnValues: ['${value.kodeTransaksi}', 
                 '${value.tanggal}', 
   '${value.listItemTransaksi.size()} Item, Total ${currencyFormat(value.total)}'])

Hasilnya akan terlihat seperti pada gambar berikut ini:

Tampilan Tabel Dengan Ekspresi Template Renderer Yang Lebih Rumit

Tampilan Tabel Dengan Ekspresi Template Renderer Yang Lebih Rumit

Saya akan lanjut melakukan perubahan berikutnya di tabel yang terletak di ItemTransaksiViewAsChild.groovy menjadi seperti berikut ini:

eventTableModel(list: model.itemTransaksiList,
  columnNames: ['Buku', 
                'Jumlah'],
  columnValues: ['${value.buku.judul}', 
                 '${value.jumlah}'])

Perubahan yang terjadi dapat dilihat pada gambar berikut ini:

Template Renderer Pada Tabel

Template Renderer Pada Tabel

Template renderer tidak hanya bisa diterapkan pada tabel, tapi juga pada comboBox(). Sebagai contoh, di ItemTransaksiViewAsChild, tampilan comboBox() untuk memilih Buku akan terlihat seperti pada gambar berikut ini:

Tampilan ComboBox Secara Default

Tampilan ComboBox Secara Default

Tampilan pada combobox tersebut pada dasarnya hanya versi toString() dari domain object. Akan lebih baik bila saya hanya menampilkan judul buku di combobox. Untuk itu, saya mengubah kode program berikut di ItemTransaksiViewAsChild.groovy menjadi seperti berikut ini:

comboBox(model: model.buku, renderer: 
    templateRenderer(template: '${value.judul}'), errorPath: 'buku')

PENTING:  Pada simple-jpa versi 0.4 ke atas, kode program di atas harus berupa:

comboBox(model: model.buku, 
    templateRenderer: '${value.judul}', errorPath: 'buku')

Sekarang, tampilan combobox akan terlihat seperti pada gambar berikut ini:

Tampilan ComboBox Setelah Perubahan Template Renderer

Tampilan ComboBox Setelah Perubahan Template Renderer

Saya juga bisa memberikan ekspresi yang lebih rumit, misalnya menampilkan judul buku dan harga secara bersamaan, dengan melakukan perubahan pada template renderer seperti berikut ini:

comboBox(model: model.buku, renderer: templateRenderer(
   template: '${value.judul} - ${currencyFormat(value.harga)}'), errorPath: 'buku')

PENTING:  Pada simple-jpa versi 0.4 ke atas, kode program di atas harus berupa:

comboBox(model: model.buku, 
   templateRenderer: '${value.judul} - ${currencyFormat(value.harga)}', errorPath: 'buku')

Tampilan combobox sekarang akan terlihat seperti pada gambar berikut ini:

Tampilan ComboBox Dengan Ekspresi Template Renderer Yang Lebih Rumit

Tampilan ComboBox Dengan Ekspresi Template Renderer Yang Lebih Rumit

Saya juga dapat menerapkan template renderer pada tagChooser(). Berikut ini adalah contoh sebuah tagChooser() yang masih segar dan tanpa perubahan:

Tampilan TagChooser Secara Default

Tampilan TagChooser Secara Default

Terlihat sangat aneh karena pada dasarnya yang ditampilkan adalah hasil toString() dari domain object. Oleh sebab itu, saya melakukan perubahan pada BukuView.groovy seperti berikut ini:

tagChooser(model: model.listPengarang, 
    templateString: '${value.namaLengkap}', 
    constraints: 'grow,push,span,wrap', 
    errorPath: 'listPengarang')

Sekarang tampilan tagChooser() akan terlihat seperti berikut ini:

Tampilan TagChooser Setelah Memakai TemplateRenderer

Tampilan TagChooser Setelah Memakai TemplateRenderer

Perihal Solid Snake
I'm nothing...

Apa komentar Anda?

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: