60 votes

Play 2.x : Comment faire une requête AJAX avec un bouton commun

J'ai déjà réussi à faire fonctionner des requêtes AJAX, mais j'ai toujours dû utiliser un formulaire, et à la fin de l'envoi, retourner false pour ne pas rafraîchir la page.

J'ai aussi récemment déplacé mon JavaScript dans un fichier séparé, ce qui a provoqué l'échec de mes commandes @. Pour cette raison, je ne sais pas comment définir l'URL de ma route ?

HTML :

<button id="saveAsDefaultButton">Save as default</button>

Code Java de Playframework :

public static Result saveDefaultPhoneForUser(String handset) {
    User currentUser = User.findByName(session("name"));
    currentUser.lastControlledHandset = theHandset;
    currentUser.save();
    return ok();
}

routes :

POST    /                           controllers.Application.saveDefaultPhoneForUser(handset : String)

javascript :

$('#saveAsDefaultButton').click(function(evt) {
        $('#errors').hide();
        $.ajax({
            type : 'POST',
            url : "controllers.Application.saveDefaultPhoneForUser",
            data : $('#controlledPhone option:selected').text(),
            dataType : "text",
            success : function(data) {
                //setError('Call succedded');
                //$('#test1').attr("src", data)
            },
            error : function(data) {
                setError('Make call failed');
            }
        });
        return false;
    });

Je suis sûr qu'il existe un moyen de le faire, mais je n'ai pas réussi à trouver quoi que ce soit.

123voto

biesior Points 29858

Pour ce travail, vous devriez opter pour javascriptRoutes car il génère des chemins JS corrects basés sur votre routes.conf. Vous trouverez un exemple d'utilisation dans Zentask échantillon

Quoi qu'il en soit, pour l'instant, vous pouvez corriger votre appel AJAX en changeant l'attribut url à

url : '@routes.Application.saveDefaultPhoneForUser()',

De cette façon, il faut placer tout le JS dans le modèle, ce qui est faux. Il peut ou même devrait être déplacé dans un fichier JS séparé et pour rendre cela possible, vous devez utiliser javascriptRoutes.

Plus...

javascriptRoutes ne sont pas décrites mais dans la documentation officielle, mais voici une introduction pas à pas. Bien que la description semble sophistiquée de facto L'utilisation de cette méthode présente de nombreux avantages.

1. Créez les routes communes

Vous devez d'abord créer des routes communes dans conf/routes archivo:

GET     /item/:id     controllers.Application.getItem(id: Long)
POST    /item/new     controllers.Application.newItem
PUT     /item/:id     controllers.Application.updateItem(id: Long)

Bien sûr, vous devez créer au moins ces trois actions dans Application contrôleur :

  • getItem(Long id){ ... }
  • newItem() { ... }
  • updateItem(Long id) { ... }

2. Créer une action traduisant les routes communes en JS

  • placez-le quelque part, par exemple dans votre Application contrôleur
  • Appelons-le javascriptRoutes()

Dans cette action, vous pointerez le existant des itinéraires de la conf/routes fichier

public static Result javascriptRoutes() {
    response().setContentType("text/javascript");
    return ok(
        Routes.javascriptRouter("myJsRoutes",
            routes.javascript.Application.getItem(),
            routes.javascript.Application.newItem(),
            routes.javascript.Application.updateItem(),
            //inside somepackage
            controllers.somepackage.routes.javascript.Application.updateItem()
        )
    );
}

Note : Ne mettez pas de paramètres entre parenthèses.

3. Créez un itinéraire pour javascriptRoutes et l'inclure dans votre modèle

Route conf/routes

GET     /javascriptRoutes     controllers.Application.javascriptRoutes

Voir dans <head> partie de /views/main.scala.html

<script type="text/javascript" src='@routes.Application.javascriptRoutes()'></script>

4. Utilisez javascriptRoutes où vous voulez

Jusqu'à présent, vous pouvez utiliser les routes en JS pour obtenir le chemin correct sans avoir besoin de spécifier l'adresse IP. url y type . Par exemple, au lieu de :

 $('.getAjaxForThisContainer').click(function(e) {
    var idToGet = $("#someField").val();
    $.ajax({
        type : 'GET',
        url : '@routes.Application.getItem()',
        data : {
            id: idToGet
        },
        success : function(data) {
            // ... some code on success
        }
    });
    return false;
});

vous pouvez utiliser une version simplifiée ( myJsRoutes du point 2) :

myJsRoutes.controllers.Application.getItem(idToGet).ajax({
    success : function(data) { ... some code ... }
});

o

myJsRoutes.controllers.Application.newItem().ajax({
    success : function(data) { ... some code ... }
});

etc...

  • vous n'avez pas besoin de spécifier type: "POST" - Le routeur JS utilisera la méthode correcte selon conf/routes règle
  • vous pouvez définir id de l'enregistrement (ou d'autres paramètres) pour GET ou PUT (ou d'autres méthodes) en utilisant routes-like syntaxe en JS pur
  • Si votre règle de route contient tous les paramètres requis, vous pouvez vraiment minimiser votre JS :

pour la route :

GET   /some/:a/:b/:c    controllers.Application.getABC(a: String, b: Integer, c: String)

JS :

myJsRoutes.controllers.Application.getABC("a", 1, "b" ).ajax({});

2 votes

Merci beaucoup Marcus. J'ai jeté un coup d'œil à l'exemple de la tâche zen, mais comme je viens de me remettre au développement web, je dois rafraîchir mes connaissances en html, css et javascript. Quand cet exemple était fait en café script ça m'a un peu rebuté. Et quand je l'ai essayé, je n'ai pas réussi à le faire fonctionner.

2 votes

De plus, Marcus, juste une petite question, si dans mon action, je fais une validation côté serveur et que je renvoie badRequest("Données incorrectes envoyées") ; je mets également une capture d'erreur dans mon javascript après le succès : error : function(data) { setError('Make call failed') ; } Comment puis-je avoir accès au String que j'ai passé. Lorsque je place le message d'erreur dans une réception, j'obtiens le résultat 'object [Object]'. Connaissez-vous un moyen pour moi de déboguer/inspecter cette information ?

2 votes

Les routes en javascript dans les documents officiels : playframework.com/documentation/2.1.1/JavaGuide6

9voto

ses Points 2924

J'aime la "bonne vieille" méthode simple :

1 Dans la page, avec JQuery,

à l'intérieur de certains even-handler

 $.get('/giveme', {'arg': value}, function(data) {

                                    window.alert(data);

                                  }
 );

2 Du côté serveur/joueur

2.1 Routes : GET /giveme controllers.Application.giveme(arg)

2.2 action scala :

object Application extends Controller { 

      def giveme(arg:String) = Action {
        Ok(Json.toJson("hello," + arg ))
      }

    }

0 votes

Puis-je utiliser plusieurs arguments dans function(data) . comme function(data, data1) .

7voto

hook38 Points 1742

Une chose à laquelle il faut faire attention... quand on appelle

Routes.javascriptRouter("myJsRoutes",

Routes est importé de play.Routes et non de play.api.Routes.

J'ai eu une erreur quand j'ai implémenté ce code, parce que j'ai supposé que cela viendrait de l'api (clairement j'avais tort). A part ça, tout fonctionne très bien~ !!

2voto

Saeed Zarinfam Points 1605

Il existe une solution plus simple : utiliser le routeur intégré pour générer un routeur Javascript. Vous pouvez générer un routeur Javascript en utilisant @javascriptRouter placez le code suivant dans la balise head de votre page html (peut-être dans le modèle de décoration principal)

<head>
    <title>Saeed Title</title>
    <link rel="shortcut icon" type="image/png" href="@routes.Assets.at("images/favicon.png")">
    <link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
    <script src="@routes.Assets.at("javascripts/jquery/v1.12.4/jquery.min.js")" type="text/javascript"></script>
    @helper.javascriptRouter("jsRoutes")(
        routes.javascript.MyController.getById,
        routes.javascript.MyController.getByName
    )
</head>

Ne vous inquiétez pas des erreurs de syntaxe (dans Intellij) et n'utilisez pas de parenthèses après le nom de votre action. Vous pouvez maintenant utiliser jsRoutes.controllers.MyController.getById(id) dans votre code d'appel ajax.

$.ajax(jsRoutes.controllers.MyController.getById(id))
   .done( /*...*/ )
   .fail( /*...*/ );

ou utiliser jsRoutes.controllers.MyController.getById(id).url pour obtenir l'url. plus d'informations .

1voto

user1434177 Points 479

La réponse de Marcus est très bonne, donc toute personne ayant ce problème devrait pouvoir l'utiliser.

J'ai cependant rencontré un problème en essayant de le faire fonctionner, ce qui m'a pris un certain temps. Lorsque j'ai fait ma requête ajax, elle était routée vers la mauvaise méthode.

C'est parce que dans mon fichier de routes, j'avais ce qui suit :

POST    /                           controllers.Application.makeCall()
POST    /                           controllers.Application.saveDefaultPhoneForUser(handset : String)

En ayant deux méthodes de poste avec le même emplacement /. Il semblait toujours aller à faire appel. Donc, juste un conseil pour tout le monde, ne faites pas cela sinon ça ne marchera pas.

J'avais juste besoin de le changer en :

POST    /                           controllers.Application.makeCall()
POST    /saveDefaultPhoneForUser    controllers.Application.saveDefaultPhoneForUser(handset : String)

J'espère que cela aidera quelqu'un.

4 votes

C'est normal, si routes contient deux règles avec la même méthode et le même chemin, seule la première sera utilisée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X