Dans play1, j'obtiens généralement toutes les données dans les actions, je les utilise directement dans les vues. Comme nous n'avons pas besoin de déclarer explicitement les paramètres dans la vue, c'est très facile.
Mais dans play2, j'ai trouvé que nous devons déclarer tous les paramètres (y compris request
) dans la tête des vues, ce sera très ennuyeux d'obtenir toutes les données dans les actions et de les passer en vues.
Par exemple, si j'ai besoin d'afficher des menus chargés à partir de la base de données sur la page d'accueil, je dois le définir dans 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>
Ensuite, je dois le déclarer dans chaque sous-page:
@(menus: Seq[Menu])
@main("SubPage", menus) {
...
}
Ensuite, je dois récupérer les menus et les transmettre à voir dans chaque action:
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))
}
Pour l'instant, ce n'est qu'un paramètre main.scala.html
, et s'il y en a plusieurs?
Alors enfin, j'ai décidé de tout Menu.findAll()
directement en vue:
@(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>
Je ne sais pas si c'est bon ou recommandé, y a-t-il une meilleure solution pour cela?
la source
Réponses:
À mon avis, le fait que les modèles soient typés statiquement est en fait une bonne chose: vous êtes assuré que l'appel de votre modèle n'échouera pas s'il se compile.
Cependant, il ajoute en effet un passe-partout sur les sites d'appel. Mais vous pouvez le réduire (sans perdre les avantages de la saisie statique).
Dans Scala, je vois deux façons d'y parvenir: via la composition d'actions ou en utilisant des paramètres implicites. En Java, je suggère d'utiliser la
Http.Context.args
carte pour stocker des valeurs utiles et les récupérer à partir des modèles sans avoir à passer explicitement comme paramètres de modèles.Utilisation de paramètres implicites
Placez le
menus
paramètre à la fin de vosmain.scala.html
paramètres de modèle et marquez-le comme «implicite»:Maintenant, si vous avez des modèles appelant ce modèle principal, vous pouvez faire passer le
menus
paramètre implicitement pour vous aumain
modèle par le compilateur Scala s'il est également déclaré en tant que paramètre implicite dans ces modèles:Mais si vous voulez le faire passer implicitement de votre contrôleur, vous devez le fournir en tant que valeur implicite, disponible dans la portée à partir de laquelle vous appelez le modèle. Par exemple, vous pouvez déclarer la méthode suivante dans votre contrôleur:
Ensuite, dans vos actions, vous pourrez simplement écrire ce qui suit:
Vous pouvez trouver plus d'informations sur cette approche dans cet article de blog et dans cet exemple de code .
Mise à jour : Un joli article de blog démontrant ce modèle a également été écrit ici .
Utilisation de la composition d'actions
En fait, il est souvent utile de transmettre la
RequestHeader
valeur aux modèles (voir par exemple cet exemple ). Cela n'ajoute pas tellement de passe-partout au code de votre contrôleur car vous pouvez facilement écrire des actions recevant une valeur de demande implicite:Ainsi, étant donné que les modèles reçoivent souvent au moins ce paramètre implicite, vous pouvez le remplacer par une valeur plus riche contenant par exemple vos menus. Vous pouvez le faire en utilisant le mécanisme de composition d'actions de Play 2.
Pour ce faire, vous devez définir votre
Context
classe en encapsulant une requête sous-jacente:Ensuite, vous pouvez définir la
ActionWithMenu
méthode suivante :Qui peut être utilisé comme ceci:
Et vous pouvez prendre le contexte comme paramètre implicite dans vos modèles. Par exemple pour
main.scala.html
:L'utilisation de la composition d'actions vous permet d'agréger toutes les valeurs implicites dont vos modèles ont besoin en une seule valeur, mais d'un autre côté, vous pouvez perdre une certaine flexibilité ...
Utilisation de Http.Context (Java)
Puisque Java n'a pas de mécanisme d'implication de Scala ou similaire, si vous voulez éviter de passer explicitement les paramètres des modèles, un moyen possible est de les stocker dans l'
Http.Context
objet qui ne vit que pendant la durée d'une requête. Cet objet contient uneargs
valeur de typeMap<String, Object>
.Ainsi, vous pouvez commencer par écrire un intercepteur, comme expliqué dans la documentation :
La méthode statique n'est qu'un raccourci pour récupérer les menus du contexte actuel. Ensuite, annotez votre contrôleur pour qu'il soit mélangé avec l'
Menus
intercepteur d'action:Enfin, récupérez la
menus
valeur de vos modèles comme suit:la source
@for(menu <- Menus.current()) {
maisMenus
n'est jamais défini (vous mettez des menus (minuscules) :)ctx.args.put("menus", Menu.find.all());
. Y a-t-il une raison? Comme Play qui le transforme en majuscules ou quelque chose comme ça?Menus
classe est définie (l'intercepteur Java). @adis Oui mais vous êtes libre de les stocker ailleurs, même dans le cache.La façon dont je le fais, consiste simplement à créer un nouveau contrôleur pour ma navigation / menu et à l'appeler depuis la vue
Ainsi, vous pouvez définir votre
NavController
:nav.scala.html
Ensuite, dans ma vue principale, je peux appeler ça
NavController
:la source
Je soutiens la réponse de stian. C'est un moyen très rapide d'obtenir des résultats.
Je viens de migrer de Java + Play1.0 vers Java + Play2.0 et les modèles sont la partie la plus difficile à ce jour, et le meilleur moyen que j'ai trouvé pour implémenter un modèle de base (pour le titre, la tête, etc.) est d'utiliser le Http .Le contexte.
Il existe une très belle syntaxe que vous pouvez obtenir avec des balises.
où get.scala.html est:
et set.scala.html est:
signifie que vous pouvez écrire ce qui suit dans n'importe quel modèle
C'est donc très lisible et agréable.
C'est la voie que j'ai choisie. stian - bon conseil. Prouve qu'il est important de faire défiler vers le bas pour voir toutes les réponses. :)
Passer des variables HTML
Je n'ai pas encore compris comment passer des variables Html.
@ (titre: Chaîne, contenu: Html)
cependant, je sais comment les passer en bloc.
@ (titre: String) (contenu: Html)
vous voudrez peut-être remplacer set.scala.html par
de cette façon, vous pouvez passer des blocs Html comme ça
EDIT: Effet secondaire avec mon implémentation "Set"
Héritage de modèle informatique de cas d'utilisation courant dans Play.
Vous avez un base_template.html, puis page_template.html qui étend base_template.html.
base_template.html pourrait ressembler à quelque chose comme
tandis que le modèle de page peut ressembler à quelque chose comme
et puis vous avez une page (supposons login_page.html) qui ressemble à
La chose importante à noter ici est que vous définissez "corps" deux fois. Une fois dans "login_page.html" puis dans "page_template.html".
Il semble que cela déclenche un effet secondaire, tant que vous implémentez set.scala.html comme je l'ai suggéré ci-dessus.
comme la page afficherait deux fois "login stuff ..." parce que put renvoie la valeur qui apparaît la deuxième fois que nous mettons la même clé. (voir mettre la signature dans les documents java).
scala fournit un meilleur moyen de modifier la carte
ce qui ne provoque pas cet effet secondaire.
la source
args
contexte après l'appel actuel.Si vous utilisez Java et que vous voulez simplement la manière la plus simple possible sans avoir à écrire un intercepteur et à utiliser l'annotation @With, vous pouvez également accéder au contexte HTTP directement à partir du modèle.
Par exemple, si vous avez besoin d'une variable disponible à partir d'un modèle, vous pouvez l'ajouter au contexte HTTP avec:
Vous pouvez ensuite y accéder depuis le modèle avec:
Évidemment, si vous jongez vos méthodes avec Http.Context.current (). Args.put ("", ""), vous feriez mieux d'utiliser un intercepteur, mais pour les cas simples, cela peut faire l'affaire.
la source
D'après la réponse de Stian, j'ai essayé une approche différente. Cela fonctionne pour moi.
EN CODE JAVA
EN TÊTE DE MODÈLE HTML
ET UTILISER COMME
la source