Di play1, saya biasanya mendapatkan semua data dalam aksi, menggunakannya langsung dalam tampilan. Karena kita tidak perlu mendeklarasikan parameter secara eksplisit, ini sangat mudah.
Namun dalam play2, saya menemukan bahwa kita harus mendeklarasikan semua parameter (termasuk request
) di kepala view, akan sangat membosankan untuk mendapatkan semua data dalam aksi dan meneruskannya ke view.
Misalnya, jika saya perlu menampilkan menu yang diambil dari basis data di halaman depan, saya harus mendefinisikannya di main.scala.html
:
@(title: String, menus: Seq[Menu])(content: Html)
<html><head><title>@title</title></head>
<body>
<div>
@for(menu<-menus) {
<a href="#">@menu.name</a>
}
</div>
@content
</body></html>
Maka saya harus mendeklarasikannya di setiap halaman:
@(menus: Seq[Menu])
@main("SubPage", menus) {
...
}
Maka saya harus mendapatkan menu dan meneruskannya untuk melihat dalam setiap tindakan:
def index = Action {
val menus = Menu.findAll()
Ok(views.html.index(menus))
}
def index2 = Action {
val menus = Menu.findAll()
Ok(views.html.index2(menus))
}
def index3 = Action {
val menus = Menu.findAll()
Ok(views.html.index(menus3))
}
Untuk saat ini hanya ada satu parameter main.scala.html
, bagaimana jika ada banyak?
Jadi akhirnya, saya memutuskan untuk Menu.findAll()
secara langsung:
@(title: String)(content: Html)
<html><head><title>@title</title></head>
<body>
<div>
@for(menu<-Menu.findAll()) {
<a href="#">@menu.name</a>
}
</div>
@content
</body></html>
Saya tidak tahu apakah itu baik atau disarankan, apakah ada solusi yang lebih baik untuk ini?
sumber
Jawaban:
Menurut pendapat saya, fakta bahwa templat diketik secara statis sebenarnya baik hal yang : Anda dijamin bahwa memanggil templat Anda tidak akan gagal jika dikompilasi.
Namun, itu memang menambahkan beberapa boilerplate di situs panggilan. Tapi Anda bisa menguranginya (tanpa kehilangan keunggulan pengetikan statis).
Di Scala, saya melihat dua cara untuk mencapainya: melalui komposisi aksi atau dengan menggunakan parameter implisit. Di Jawa saya sarankan menggunakan
Http.Context.args
peta untuk menyimpan nilai-nilai berguna dan mengambilnya dari template tanpa harus secara eksplisit lulus sebagai parameter template.Menggunakan parameter implisit
Tempatkan
menus
parameter di akhirmain.scala.html
parameter template Anda dan tandai sebagai "implisit":Sekarang jika Anda memiliki template yang memanggil template utama ini, Anda dapat memiliki
menus
parameter yang secara implisit dilimpahkan untuk Anda kemain
templat oleh kompilator Scala jika dinyatakan sebagai parameter implisit dalam templat ini juga:Tetapi jika Anda ingin secara implisit dilewatkan dari pengontrol Anda, Anda harus memberikannya sebagai nilai implisit, tersedia dalam ruang lingkup tempat Anda memanggil templat. Misalnya, Anda dapat mendeklarasikan metode berikut di controller Anda:
Maka dalam tindakan Anda, Anda hanya dapat menulis yang berikut ini:
Anda dapat menemukan informasi lebih lanjut tentang pendekatan ini di posting blog ini dan di contoh kode ini .
Memperbarui : Posting blog yang bagus menunjukkan pola ini juga telah ditulis di sini .
Menggunakan komposisi aksi
Sebenarnya, sering berguna untuk meneruskan
RequestHeader
nilai ke templat (lihat misalnya sampel ini ). Ini tidak menambah terlalu banyak pelat ke kode pengontrol Anda karena Anda dapat dengan mudah menulis tindakan yang menerima nilai permintaan implisit:Jadi, karena templat sering menerima setidaknya parameter implisit ini, Anda bisa menggantinya dengan nilai yang lebih kaya yang mengandung misalnya menu Anda. Anda dapat melakukannya dengan menggunakan komposisi aksi mekanisme dari Play 2.
Untuk melakukan itu Anda harus mendefinisikan
Context
kelas Anda , membungkus permintaan yang mendasarinya:Kemudian Anda dapat menentukan
ActionWithMenu
metode berikut :Yang bisa digunakan seperti ini:
Dan Anda dapat mengambil konteks sebagai parameter implisit dalam template Anda. Misalnya untuk
main.scala.html
:Menggunakan komposisi tindakan memungkinkan Anda untuk mengumpulkan semua nilai implisit yang diperlukan template Anda menjadi nilai tunggal, tetapi di sisi lain Anda dapat kehilangan beberapa fleksibilitas ...
Menggunakan Http.Context (Java)
Karena Java tidak memiliki mekanisme implisit Scala atau yang serupa, jika Anda ingin menghindari untuk secara eksplisit melewatkan parameter templat, cara yang mungkin adalah dengan menyimpannya di
Http.Context
objek yang hanya hidup selama durasi permintaan. Objek ini mengandungargs
nilai tipeMap<String, Object>
.Dengan demikian, Anda bisa mulai dengan menulis interseptor, seperti yang dijelaskan dalam dokumentasi :
Metode statis hanyalah singkatan untuk mengambil menu dari konteks saat ini. Lalu beri catatan pengontrol Anda untuk dicampur dengan
Menus
tindakan pencegat:Terakhir, ambil
menus
nilai dari templat Anda sebagai berikut:sumber
@for(menu <- Menus.current()) {
tetapiMenus
tidak pernah ditentukan (Anda meletakkan menu (huruf kecil)ctx.args.put("menus", Menu.find.all());
:). Apakah ada alasan? Seperti Play yang mengubahnya menjadi huruf besar atau semacamnya?Menus
kelas yang ditentukan (pencegat Java). @adis Ya tapi Anda bebas menyimpannya di tempat lain, bahkan di cache.Cara saya melakukannya, adalah dengan hanya membuat controller baru untuk menu / navigasi saya dan memanggilnya dari tampilan
Jadi, Anda dapat menentukan
NavController
:nav.scala.html
Kemudian di tampilan utama saya, saya bisa menyebutnya
NavController
:sumber
Saya mendukung jawaban stian. Ini adalah cara yang sangat cepat untuk mendapatkan hasil.
Saya baru saja bermigrasi dari Java + Play1.0 ke Java + Play2.0 dan templat adalah bagian tersulit sejauh ini, dan cara terbaik yang saya temukan untuk mengimplementasikan templat dasar (untuk judul, head dll.) Adalah dengan menggunakan Http .Konteks.
Ada sintaks yang sangat bagus yang bisa Anda capai dengan tag.
di mana get.scala.html adalah:
dan set.scala.html adalah:
berarti Anda dapat menulis yang berikut dalam templat apa pun
Jadi itu sangat enak dibaca dan bagus.
Ini adalah cara saya memilih untuk pergi. stian - saran yang bagus. Buktikan bahwa penting untuk menggulir ke bawah untuk melihat semua jawaban. :)
Melewati variabel HTML
Saya belum menemukan cara untuk melewatkan variabel Html.
@ (judul: String, konten: Html)
Namun, saya tahu cara melewatinya sebagai blok.
@ (judul: String) (konten: Html)
jadi Anda mungkin ingin mengganti set.scala.html dengan
dengan cara ini Anda dapat melewati blok Html seperti itu
EDIT: Efek Samping Dengan Implementasi "Set" Saya
Kasus penggunaan umum itu templat warisan di Play.
Anda memiliki base_template.html dan kemudian Anda memiliki page_template.html yang meluas base_template.html.
base_template.html mungkin terlihat seperti
sementara templat laman mungkin terlihat seperti
dan kemudian Anda memiliki halaman (mari kita asumsikan login_page.html) yang terlihat seperti
Yang penting untuk diperhatikan di sini adalah Anda mengatur "tubuh" dua kali. Setelah di "login_page.html" dan kemudian di "page_template.html".
Tampaknya ini memicu efek samping, selama Anda menerapkan set.scala.html seperti yang saya sarankan di atas.
karena halaman akan menampilkan "barang masuk ..." dua kali karena put mengembalikan nilai yang muncul kedua kalinya kami memasukkan kunci yang sama. (lihat menaruh tanda tangan di java docs).
scala menyediakan cara yang lebih baik untuk memodifikasi peta
yang tidak menyebabkan efek samping ini.
sumber
args
konteks panggilan setelah panggilan saat ini.Jika Anda menggunakan Java dan hanya ingin cara termudah yang mungkin tanpa harus menulis interseptor dan menggunakan penjelasan @Dengan, Anda juga dapat mengakses konteks HTTP langsung dari templat.
Misalnya, jika Anda memerlukan variabel yang tersedia dari templat, Anda dapat menambahkannya ke konteks HTTP dengan:
Anda kemudian dapat mengaksesnya dari templat dengan:
Tentunya jika Anda mengotori metode Anda dengan Http.Context.current (). Args.put ("", "") Anda lebih baik menggunakan pencegat, tetapi untuk kasus-kasus sederhana itu dapat melakukan trik.
sumber
Dari jawaban Stian, saya mencoba pendekatan yang berbeda. Ini bekerja untuk saya.
DALAM KODE JAWA
DALAM KEPALA TEMPLATE HTML
DAN GUNAKAN SEPERTI
sumber