Apache Tapestry - Komponen
Seperti yang telah dibahas sebelumnya, Komponen dan Halaman adalah sama kecuali Halaman adalah komponen root dan menyertakan satu atau beberapa komponen anak. Komponen selalu berada di dalam halaman dan melakukan hampir semua fungsi dinamis halaman.
Komponen permadani membuat tautan HTML sederhana ke fungsionalitas kisi yang kompleks dengan interactive AJAX. Komponen juga dapat menyertakan komponen lain. Komponen permadani terdiri dari item berikut -
Component Class - Kelas utama Java dari komponen tersebut.
XML Template- Template XML mirip dengan template Halaman. Kelas komponen menjadikan template sebagai hasil akhir. Beberapa komponen mungkin tidak memiliki template. Dalam hal ini, keluaran akan dihasilkan oleh kelas komponen itu sendiri dengan menggunakanMarkupWriter kelas.
Body- Komponen yang ditentukan di dalam template halaman mungkin memiliki markup kustom dan disebut "Badan komponen". Jika template komponen memiliki<body />elemen, maka elemen <body /> akan digantikan oleh tubuh komponen. Ini mirip dengan tata letak yang dibahas sebelumnya di bagian template XML.
Rendering - Rendering adalah proses yang mengubah template XML dan isi komponen menjadi keluaran aktual komponen.
Parameters - Digunakan untuk membuat komunikasi antara komponen & halaman dan dengan demikian meneruskan data di antara mereka.
Events- Mendelegasikan fungsionalitas dari komponen ke penampung / induknya (halaman atau komponen lain). Ini banyak digunakan dalam tujuan navigasi halaman.
Merender
Rendering komponen dilakukan dalam serangkaian fase yang telah ditentukan sebelumnya. Setiap fase dalam sistem komponen harus memiliki metode terkait yang ditentukan oleh konvensi atau penjelasan dalam kelas komponen.
// Using annotaion
@SetupRender
void initializeValues() {
// initialize values
}
// using convention
boolean afterRender() {
// do logic
return true;
}
Tahapan, nama metode dan penjelasannya tercantum di bawah ini.
Anotasi | Nama Metode Default |
---|---|
@Tokopedia | setupRender () |
@Bayu_joo | beginRender () |
@Templek_indonesia | beforeRenderTemplate () |
@Septianjoko_ | beforeRenderBody () |
@SetelahDetik | afterRenderBody () |
@Template_template | afterRenderTemplate () |
@Setelahnya | afterRender () |
@Tokopedia | cleanupRender () |
Setiap fase memiliki tujuan tertentu dan itu adalah sebagai berikut -
SetupRender
SetupRender memulai proses rendering. Biasanya mengatur parameter komponen.
BeginRender
BeginRender mulai merender komponen. Ini biasanya membuat tag start / start dari komponen.
BeforeRenderTemplate
BeforeRenderTemplate digunakan untuk menghias template XML, menambahkan markup khusus di sekitar template. Ini juga menyediakan opsi untuk melewati rendering template.
BeforeRenderBody
BeforeRenderTemplate menyediakan opsi untuk melewati rendering elemen badan komponen.
AfterRenderBody
AfterRenderBody akan dipanggil setelah badan komponen dirender.
AfterRenderTemplate
AfterRenderTemplate akan dipanggil setelah template komponen dirender.
AfterRender
AfterRender adalah pasangan dari BeginRender dan biasanya membuat tag penutup.
CleanupRender
CleanupRender adalah mitra dari SetupRender. Ini melepaskan / membuang semua objek yang dibuat selama proses rendering.
Alur tahapan rendering tidak hanya diteruskan. Ini pergi ke sana kemari antara fase tergantung pada nilai kembali fase.
Misalnya, jika metode SetupRender mengembalikan false, rendering akan melompat ke fase CleanupRender dan sebaliknya. Untuk menemukan pemahaman yang jelas tentang aliran antara fase yang berbeda, periksa aliran dalam diagram yang diberikan di bawah ini.
Komponen Sederhana
Mari kita buat komponen sederhana, Hello yang akan memiliki pesan keluaran sebagai "Hello, Tapestry". Berikut ini adalah kode komponen Hello dan templatenya.
package com.example.MyFirstApplication.components;
public class Hello {
}
<html
xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<div>
<p>Hello, Tapestry (from component).</p>
</div>
</html>
Komponen Hello bisa dipanggil di template halaman sebagai -
<html title = "Hello component test page"
xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<t:hello />
</html>
Demikian pula, komponen dapat membuat keluaran yang sama menggunakan MarkupWriter alih-alih template seperti yang ditunjukkan di bawah ini.
package com.example.MyFirstApplication.components;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.BeginRender;
public class Hello {
@BeginRender
void renderMessage(MarkupWriter writer) {
writer.write("<p>Hello, Tapestry (from component)</p>");
}
}
Mari kita ubah template komponen dan sertakan elemen <body /> seperti yang ditunjukkan pada blok kode di bawah ini.
<html>
xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<div>
<t:body />
</div>
</html>
Sekarang, templat halaman mungkin menyertakan badan dalam markup komponen seperti yang ditunjukkan di bawah ini.
<html title = "Hello component test page"
xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<t:hello>
<p>Hello, Tapestry (from page).</p>
</t:hello>
</html>
Outputnya adalah sebagai berikut -
<html>
<div>
<p>Hello, Tapestry (from page).</p>
</div>
</html>
Parameter
Tujuan utama dari parameter ini adalah untuk membuat koneksi antara bidang komponen dan properti / sumber daya laman. Menggunakan parameter, komponen, dan halaman yang sesuai untuk berkomunikasi dan mentransfer data antara satu sama lain. Ini disebutTwo Way Data Binding.
Misalnya, komponen kotak teks yang digunakan untuk mewakili usia di halaman pengelolaan pengguna mendapatkan nilai awalnya (tersedia di database) melalui parameter. Sekali lagi, setelah usia pengguna diperbarui dan dikirimkan kembali, komponen akan mengirimkan kembali usia yang diperbarui melalui parameter yang sama.
Untuk membuat parameter baru di kelas komponen, deklarasikan bidang dan tentukan @Parameteranotasi. @Parameter ini memiliki dua argumen opsional, yaitu -
required- menjadikan parameter sebagai wajib. Permadani menimbulkan pengecualian jika tidak disediakan.
value - menentukan nilai default dari parameter.
Parameter harus ditentukan dalam template halaman sebagai atribut dari tag komponen. Nilai atribut harus ditentukan menggunakan Binding Expression / Expansion, yang telah kita bahas di bab sebelumnya. Beberapa perluasan yang kita pelajari sebelumnya adalah -
Property expansion (prop:«val») - Dapatkan data dari properti kelas halaman.
Message expansion (message:«val») - Dapatkan data dari kunci yang ditentukan dalam file index.properties.
Context expansion (context:«val») - Dapatkan data dari folder konteks web / src / main / webapp.
Asset expansion (asset:«val») - Dapatkan data dari sumber daya yang tertanam dalam file jar, / META-INF / assets.
Symbol expansion (symbol:«val») - Dapatkan data dari simbol yang ditentukan di AppModule.javafile.
Permadani memiliki lebih banyak ekspansi yang berguna, beberapa di antaranya diberikan di bawah ini -
Literal expansion (literal:«val») - String literal.
Var expansion (var:«val») - Izinkan variabel render dari komponen untuk dibaca atau diperbarui.
Validate expansion (validate:«val»)- String khusus yang digunakan untuk menentukan aturan validasi suatu objek. Sebagai Contoh, validasi: wajibkan, minLength = 5.
Translate (translate:«val») - Digunakan untuk menentukan kelas Penerjemah (mengonversi representasi sisi klien ke sisi server) dalam validasi input.
Block (block:«val») - Id elemen blok di dalam template.
Component (component:«val») - Id komponen lain di dalam template.
Semua perluasan di atas bersifat hanya baca kecuali perluasan Properti dan perluasan Var. Mereka digunakan oleh komponen untuk bertukar data dengan halaman. Saat menggunakan perluasan sebagai nilai atribut,${...}sebaiknya tidak digunakan. Sebagai gantinya gunakan saja ekspansi tanpa simbol dolar dan tanda kurung.
Komponen Menggunakan Parameter
Mari kita buat komponen baru, HelloWithParameter dengan memodifikasi komponen Hello untuk merender pesan secara dinamis dengan menambahkan name parameter di kelas komponen dan mengubah template komponen dan template halaman yang sesuai.
Buat kelas komponen baru HelloWithParameter.java.
Tambahkan bidang pribadi dan beri nama dengan @Parameteranotasi. Gunakan argumen yang diperlukan untuk menjadikannya wajib.
@Parameter(required = true)
private String name;
Tambahkan bidang pribadi, hasil dengan @Properyanotasi. Properti result akan digunakan di template komponen. Template komponen tidak memiliki akses ke bidang yang diberi anotasi@Parameter dan hanya dapat mengakses bidang yang diberi anotasi @Property. Variabel yang tersedia di template komponen disebut Variabel Render.
@Property
private String result;
Tambahkan metode RenderBody dan salin nilai dari parameter name ke properti result.
@BeginRender
void initializeValues() {
result = name;
}
Tambahkan template komponen baru HelloWithParamter.tml dan menggunakan properti result untuk merender pesan.
<div> Hello, ${result} </div>
Tambahkan properti baru, Nama pengguna di halaman pengujian (testhello.java).
public String getUsername() {
return "User1";
}
Gunakan komponen yang baru dibuat di template halaman dan setel properti Nama pengguna di parameter nama HelloWithParameter komponen.
<t:helloWithParameter name = "username" />
Daftar lengkapnya adalah sebagai berikut -
package com.example.MyFirstApplication.components;
import org.apache.tapestry5.annotations.*;
public class HelloWithParameter {
@Parameter(required = true)
private String name;
@Property
private String result;
@BeginRender
void initializeValues() {
result = name;
}
}
<html
xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<div> Hello, ${result} </div>
</html>
package com.example.MyFirstApplication.pages;
import org.apache.tapestry5.annotations.*;
public class TestHello {
public String getUsername() {
return "User1";
}
}
<html title = "Hello component test page"
xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<t:helloWithParameter name = "username" />
</html>
Hasilnya adalah sebagai berikut -
<div> Hello, User1 </div>
Parameter Lanjutan
Di bab sebelumnya, kami menganalisis cara membuat dan menggunakan parameter sederhana di komponen kustom. Parameter lanjutan mungkin berisi markup lengkap juga. Dalam kasus ini, markup harus ditentukan di dalam tag komponen seperti sub-bagian di template halaman. Komponen built-in if memiliki markup untuk kondisi sukses dan gagal. Markup untuk sukses ditentukan sebagai badan dari tag komponen dan markup kegagalan ditentukan menggunakan sebuahelseparameter.
Mari kita lihat cara menggunakan ifkomponen. Komponen if memiliki dua parameter -
test - Parameter berbasis properti sederhana.
Else - Parameter lanjutan digunakan untuk menentukan markup alternatif, jika kondisi gagal
Tapestry akan memeriksa nilai properti uji menggunakan logika berikut dan mengembalikan benar atau salah. Ini disebutType Coercion, cara untuk mengonversi objek dari satu jenis ke jenis lain dengan konten yang sama.
Jika tipe datanya adalah String, "True" jika tidak kosong dan bukan string literal "False" (tidak peka huruf besar / kecil).
Jika tipe datanya adalah Number, Benar jika bukan nol.
Jika tipe datanya adalah Collection, Benar jika tidak kosong.
Jika tipe datanya adalah Object, Benar (selama tidak null).
Jika kondisi lolos, komponen akan merender tubuhnya; jika tidak, itu membuat badan dari parameter else.
Daftar lengkapnya adalah sebagai berikut -
package com.example.MyFirstApplication.pages;
public class TestIf {
public String getUser() {
return "User1";
}
}
<html title = "If Test Page"
xmlns:t = "http://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<body>
<h1>Welcome!</h1>
<t:if test = "user">
Welcome back, ${user}
<p:else>
Please <t:pagelink page = "login">Login</t:pagelink>
</p:else>
</t:if>
</body>
</html>
Acara Komponen / Navigasi Halaman
Aplikasi permadani adalah a collection of Pagesberinteraksi satu sama lain. Sampai sekarang, kami telah mempelajari cara membuat halaman individual tanpa komunikasi di antara mereka. Tujuan utama peristiwa Komponen adalah untuk menyediakan interaksi antar halaman (juga di dalam halaman) menggunakan peristiwa sisi server. Sebagian besar peristiwa komponen berasal dari peristiwa sisi klien.
Misalnya, ketika pengguna mengklik link di halaman, Tapestry akan memanggil halaman yang sama itu sendiri dengan informasi target alih-alih memanggil halaman target dan memunculkan acara sisi server. Halaman tapestry akan menangkap acara tersebut, memproses informasi target dan melakukan pengalihan sisi server ke halaman target.
Permadani mengikuti a Post/Redirect/Get (RPG) design patternuntuk navigasi halaman. Dalam RPG, ketika pengguna melakukan permintaan posting dengan mengirimkan formulir, server akan memproses data yang diposting, tetapi tidak mengembalikan respons secara langsung. Sebaliknya, itu akan melakukan pengalihan sisi klien ke halaman lain, yang akan menampilkan hasilnya. Pola RPG digunakan untuk mencegah pengiriman formulir duplikat melalui tombol kembali browser, tombol refresh browser, dll., Tapestry menyediakan pola RPG dengan menyediakan dua jenis permintaan berikut.
Component Event Request- Jenis permintaan ini menargetkan komponen tertentu di halaman dan memunculkan peristiwa di dalam komponen tersebut. Permintaan ini hanya melakukan pengalihan dan tidak mengeluarkan respons.
Render Request - Jenis permintaan ini menargetkan halaman dan mengalirkan respons kembali ke klien.
Untuk memahami event komponen dan navigasi halaman, kita perlu mengetahui pola URL dari permintaan permadani. Pola URL untuk kedua jenis permintaan adalah sebagai berikut -
Component Event Requests -
/<<page_name_with_path>>.<<component_id|event_id>>/<<context_information>>
Render Request -
/<<page_name_with_path>>/<<context_information>>
Beberapa contoh pola URL adalah -
Halaman indeks dapat diminta oleh https://«domain»/«app»/index.
Jika halaman Indeks tersedia di bawah admin sub-folder, maka halaman tersebut dapat diminta oleh https://«domain»/«app»/admin/index.
Jika pengguna mengklik ActionLink component dengan id test di halaman indeks, maka URL-nya akan menjadi https://«domain»/«app»/index.test.
Acara
Secara default, Permadani muncul OnPassivate dan OnActivateacara untuk semua permintaan. Untuk jenis permintaan acara Komponen, tapestry memunculkan satu atau lebih acara tambahan bergantung pada komponen. Komponen ActionLink memunculkan event Action, sedangkan komponen Form memunculkan beberapa event sepertiValidate, Success, dll.,
Peristiwa bisa ditangani di kelas halaman menggunakan penangan metode yang sesuai. Penangan metode dibuat baik melalui konvensi penamaan metode atau melalui@OnEventanotasi. Format konvensi penamaan metode adalahOn«EventName»From«ComponentId».
Peristiwa aksi komponen ActionLink dengan id test dapat ditangani dengan salah satu metode berikut -
void OnActionFromTest() {
}
@OnEvent(component = "test", name = "action")
void CustomFunctionName() {
}
Jika nama metode tidak memiliki komponen tertentu, maka metode akan dipanggil untuk semua komponen dengan kejadian yang cocok.
void OnAction() {
}
Acara OnPassivate dan OnActivate
OnPassivate digunakan untuk menyediakan informasi konteks untuk pengendali kejadian OnActivate. Secara umum, Tapestry menyediakan informasi konteks dan dapat digunakan sebagai argumen di handler OnActivateevent.
Misalnya, jika informasi konteks adalah 3 tipe int, maka acara OnActivate bisa disebut sebagai -
void OnActivate(int id) {
}
Dalam beberapa skenario, informasi konteks mungkin tidak tersedia. Dalam situasi ini, kami dapat memberikan informasi konteks ke pengendali kejadian OnActivate melalui pengendali kejadian OnPassivate. Jenis kembalian pengendali kejadian OnPassivate harus digunakan sebagai argumen pengendali kejadian OnActivate.
int OnPassivate() {
int id = 3;
return id;
}
void OnActivate(int id) {
}
Nilai Pengembalian Event Handler
Permadani masalah pengalihan halaman berdasarkan nilai yang dikembalikan dari event handler. Penangan kejadian harus mengembalikan salah satu dari nilai berikut.
Null Response- Mengembalikan nilai nol. Permadani akan membuat URL halaman saat ini dan mengirim ke klien sebagai pengalihan.
public Object onAction() {
return null;
}
String Response- Mengembalikan nilai string. Permadani akan membuat URL halaman yang cocok dengan nilai dan mengirim ke klien sebagai pengalihan.
public String onAction() {
return "Index";
}
Class Response- Mengembalikan kelas halaman. Tapestry akan membuat URL dari kelas halaman yang dikembalikan dan dikirim ke klien sebagai pengalihan.
public Object onAction() {
return Index.class
}
Page Response- Mengembalikan bidang yang dianotasi dengan @InjectPage. Tapestry akan membuat URL dari halaman yang diinjeksi dan mengirim ke klien sebagai pengalihan.
@InjectPage
private Index index;
public Object onAction(){
return index;
}
HttpError- Mengembalikan objek HTTPError. Permadani akan mengeluarkan kesalahan HTTP sisi klien.
public Object onAction(){
return new HttpError(302, "The Error message);
}
Link Response- Mengembalikan contoh tautan secara langsung. Tapestry akan membuat URL dari objek Link dan dikirim ke klien sebagai pengalihan.
Stream Response - Mengembalikan StreamResponseobyek. Tapestry akan mengirimkan aliran sebagai respon langsung ke browser klien. Ini digunakan untuk menghasilkan laporan dan gambar secara langsung dan mengirimkannya ke klien.
Url Response - Mengembalikan java.net.URLobyek. Tapestry akan mendapatkan URL yang sesuai dari objek dan dikirim ke klien sebagai pengalihan.
Object Response- Mengembalikan nilai apapun selain di atas nilai yang ditentukan. Permadani akan memunculkan kesalahan.
Konteks Acara
Secara umum, event handler bisa mendapatkan informasi konteks menggunakan argumen. Misalnya, jika informasi konteksnya adalah 3 tipe int, maka event handlernya adalah -
Object onActionFromTest(int id) {
}
Tapestry dengan benar menangani informasi konteks dan memberikannya ke metode melalui argumen. Terkadang, Tapestry mungkin tidak dapat menanganinya dengan benar karena kerumitan pemrograman. Pada saat itu, kami dapat memperoleh informasi konteks lengkap dan memprosesnya sendiri.
Object onActionFromEdit(EventContext context) {
if (context.getCount() > 0) {
this.selectedId = context.get(0);
} else {
alertManager.warn("Please select a document.");
return null;
}
}