web-dev-qa-db-fra.com

Comment utiliser les méthodes Meteor dans un assistant de modèle

Comment puis-je définir une méthode Meteor qui peut également être appelée dans un assistant de modèle?

J'ai ces deux fichiers:

fichier: lib/test.js

Meteor.methods({
    viewTest : function (str) {
        return str;
    }
});

fichier: client/myView.js

Template.helloWorld.helpers({
    txt : function () {
        var str = Meteor.call('viewTest', 'Hello World.');
        return str;
    }
});

Quand je donne à "str" ​​une chaîne normale, tout fonctionne bien. Mais dans ce cas, mon modèle n'a aucune valeur. J'ai défini - pour le test - dans le même fichier où la méthode est une fonction normale et j'ai essayé d'appeler la fonction. L'erreur que j'ai eue est que la fonction n'existe pas. Je pense donc que Meteor essaie de rendre le modèle avant de connaître les méthodes que j'ai définies pour lui. Mais je pense que c'est un peu inhabituel - n'est-ce pas?

38
TJR

Il existe maintenant une nouvelle façon de le faire (Meteor 0.9.3.1) qui ne pollue pas l'espace de noms Session

Template.helloWorld.helpers({
    txt: function () {
        return Template.instance().myAsyncValue.get();
    }
});

Template.helloWorld.created = function (){
    var self = this;
    self.myAsyncValue = new ReactiveVar("Waiting for response from server...");
    Meteor.call('getAsyncValue', function (err, asyncValue) {
        if (err)
            console.log(err);
        else 
            self.myAsyncValue.set(asyncValue);
    });
}

Dans le rappel 'créé', vous créez une nouvelle instance d'un ReactiveVariable (voir docs ) et vous l'attachez à l'instance de modèle.

Vous appelez ensuite votre méthode et lorsque le rappel se déclenche, vous attachez la valeur renvoyée à la variable réactive.

Vous pouvez ensuite configurer votre assistant pour renvoyer la valeur de la variable réactive (qui est maintenant attachée à l'instance de modèle), et elle sera réexécutée lorsque la méthode reviendra.

Mais notez que vous devrez ajouter le package reactive-var pour que cela fonctionne

$ meteor add reactive-var
57
Petrov

Sashko a ajouté un petit paquet soigné appelé meteor-reactive-method pour résoudre ce problème.

$ meteor add simple:reactive-method
Template.helloWorld.helpers({
  txt: function() {
    return ReactiveMethod.call('viewTest', 'Hello World.');
  }
});

Comme je le souligne dans erreurs courantes , les assistants doivent être exempts d'effets secondaires, donc j'utiliserais cette technique avec prudence. Cependant, c'est un raccourci vraiment pratique pour les cas où:

  • L'assistant ne doit tirer qu'une seule fois (cela ne dépend pas de l'état réactif).
  • La méthode invoquée ne mute pas la base de données.
23
David Weldon

Vous devez interfacer votre valeur de retour avec une variable de session car la demande est asynchrone:

Template.helloWorld.helpers({
    txt : function () {
        return Session.get("txt") || "Loading";
    }
});

Template.helloWorld.created = function() {
    Meteor.call('viewTest', 'Hello World.', function(err, result) {
        Session.set("txt", result);
    });

}

Donc .rendered devrait être appelé une fois lors du chargement de votre modèle (du moins, il devrait l'être avec la nouvelle version de Meteor.)

La valeur serait appelée et affichée. Sinon, il indiquerait "Chargement".

12
Akshat

Les méthodes côté client sont asynchrones et leur valeur de retour n'est toujours pas définie. Pour obtenir la valeur réelle retournée par la méthode, vous devez fournir un rappel:

Meteor.call('method', 'argument', function(error, result) {
    ....
});

Maintenant, il n'y a pas de moyen facile d'utiliser le résultat dans votre assistant. Cependant, vous pouvez le stocker dans votre modèle en tant qu'objet de données, puis le renvoyer dans l'aide:

Template.template.created = function() {
    var self = this;
    self.data.elephantDep = new Deps.Dependency();
    self.data.elephant = '';
    Meteor.call('getElephant', 'greenOne', function(error, result) {
        self.data.elephant = result;
        self.data.elephantDep.changed();
    });
};

Template.template.showElephant = function() {
    this.elephantDep.depend();
    return this.elephant;
};
11
Hubert OG

Il s'agit d'un comportement attendu. Vous n'utilisez pas methods comme prévu.

Votre code définit une méthode serveur viewTest et un stub de méthode correspondant sur le client du même nom.

Meteor.call('viewTest', 'Hello World.'); appelle à distance viewTest sur le serveur et exécute en parallèle le stub sur le client.

Concernant la valeur de retour du stub, veuillez consulter la documentation ici , en particulier:

Sur le client, la valeur de retour d'un stub est ignorée. Les stubs sont exécutés pour leurs effets secondaires: ils sont destinés à simuler le résultat de ce que fera la méthode du serveur, mais sans attendre le délai d'aller-retour.

Concernant la valeur de retour de la méthode serveur, veuillez consulter la documentation ici , en particulier:

Sur le client, si vous ne passez pas de rappel et que vous n'êtes pas dans un stub, l'appel renverra non défini et vous n'aurez aucun moyen d'obtenir la valeur de retour de la méthode. C'est parce que le client n'a pas de fibres, donc il n'y a aucun moyen de bloquer l'exécution à distance d'une méthode.

2
Tobold

Il y a un bon petit paquet pour ça par @msavin:
https://atmospherejs.com/msavin/fetcher

0
avalanche1