web-dev-qa-db-fra.com

Existe-t-il un moyen de passer des variables dans des modèles dans Meteor?

J'ai expérimenté Meteor et j'ai rencontré quelque chose que je ne pouvais pas comprendre. Pour le plaisir, j'essayais de faire une machine à sous. J'avais le HTML suivant:

<div class="slot-wrapper">
  {{> slot}}
  {{> slot}}
  {{> slot}}
</div>

<template name="slot">
  <div class="slot">
    <div class="number"><span>{{ number }}</span></div>
    <div class="divider"></div>
  </div>
</template>

Je veux avoir un numéro différent pour chaque emplacement. Est-il possible de passer des variables dans un modèle? Quelque chose comme ça:

<div class="slot-wrapper">
  {{> slot 1}}
  {{> slot 2}}
  {{> slot 3}}
</div>

<template name="slot">
  <div class="slot">
    <div class="number"><span>{{ number i}}</span></div>
    <div class="divider"></div>
  </div>
</template>

Peut-être que je pense à cela de la mauvaise façon et qu'il y a une meilleure façon.

62
Jordan Brown

Toutes les réponses précédentes sont excessives ou obsolètes. Voici comment vous pouvez passer des paramètres statiques dans des modèles, directement à partir du code HTML + Spacebars, à partir de Meteor 0.8.x:

<div class="slot-wrapper">
  {{> slot number="1"}}
  {{> slot number="2"}}
  ...
</div>

<template name="slot">
  <div class="number"><span>{{number}}</span></div>
</template>

Tout ce que vous avez à faire est de réussir key="value" paramètres dans {{> template}} appel d'inclusion:

{{> slot number="1"}}

En savoir plus sur Spacebars Secrets: Exploring Meteor Templates .


Si vous souhaitez transmettre les données du modèle d'appelant au modèle enfant/imbriqué/appelé, voici comment procéder: ne rien transmettre. Au lieu de cela, à partir du modèle imbriqué, accédez au contexte de données parent, ../:

<div class="slot-wrapper">
  {{> slot number="1"}}
  {{> slot number="2"}}
  ...
</div>

<template name="slot">
  <div>Machine name: {{../name}}</div>
  <div class="number"><span>{{number}}</span></div>
</template>
90
Dan Dascalescu

Il s'avère qu'il y a une autre façon.

J'essayais de savoir comment faire cela en recherchant diverses recherches sur Google et en trouvant cette question, mais rien qui convenait à mon objectif. La réponse de TomUnite fonctionne sauf si vous souhaitez placer les modèles imbriqués à différents endroits dans le modèle parent.

Donc, après de nombreuses recherches, j'ai trouvé "une" réponse dans la base de code des météores. (Je ne dis pas que c'est la réponse définitive mais ça marche)

<template name="slots">
  {{> slot one}}
  <div>..something else</div>
  {{> slot three}}
  {{> slot two}}
</template>

<template name="slot">
  <div class="slot">
    <div class="number"><span>{{number}}</span></div>
    <div class="divider"></div>
  </div>
</template>

Comme vous le voyez, nous pouvons spécifier les instances de modèle dans n'importe quel ordre. Le deuxième paramètre est en fait une variable qui doit être définie, donc:

Template.slots.one = {
  number: 1
}
Template.slots.two = {
  number: 2
}
Template.slots.three = {
  number: 3
}

Cela pourrait être transformé en un code plus succinct avec une boucle ou peut-être en utilisant la fonction underscore.js _.extend sur l'objet slots. De plus, nous pouvons transmettre plusieurs champs de données à ces objets.

14
Joc

Je voulais laisser cela comme un commentaire, parce que c'est juste une clarification de la réponse de Joc, mais je n'ai pas pu, alors voici avec plus l'exemple avec lequel j'ai travaillé.

Un seul argument peut être transmis au modèle:

{{> singleItemInfo arg1}}

cet argument doit être un objet tel que:

{
    number: 1,
    number2: 2,
    numberComposite: {
        subnum1: 10,
        subnum2: 20
    }
};

les valeurs des arguments sont accessibles via leurs clés, et la portée peut être changée pour obtenir les sous-éléments avec le

{{#with numberComposite}}

Voici le code complet de l'exemple:

<fichier html>

<body>
    {{ itemsView }}
</body>

<template name="itemsView">
    {{> singleItemInfo arg1}}
</template>

<template name="singleItemInfo">
    arg1 = {{ number }}
    arg2 = {{ number2 }} 
    {{#with numberComposite}}
        subArg1 = {{ subnum1 }}
        subArg2 = {{ subnum2 }}
    {{/with}}
</template>

<fichier javascript>

Template.itemsView.arg1 = {
    number: 1,
    number2: 2,
    numberComposite: {
        subnum1: 10,
        subnum2: 20
    }
};

SORTIE:

arg1 = 1 arg2 = 2 subArg1 = 10 subArg2 = 20 
9
jay

Meilleure réponse:

Les deux solutions disponibles pour rendre un modèle contextuel sous la nouvelle disposition Blaze sont les suivantes:

1) Passer des arguments directement au modèle

{{> contextSensitiveTemplate  context_1='x' context_2='y' }}

2) Utiliser un assistant dans le modèle qui comprend le contexte. Appelez l'assistant comme ceci:

{{ contextHelperName ../.. .. this }}

Et

Template.contextSensitiveTemplate.contextHelperName = function(parent_template, current_template, current_value_inside_each_loop) {
  return context_dependent_value_or_html     
}
5
Jim

C'est ce que j'ai fait pour y parvenir. Je suis assez nouveau sur Meteor, donc il y a peut-être un meilleur moyen:

Slot.html:

<head>
  <title>Slot</title>
</head>

<body>
  <div class="slot-wrapper">
    {{> slots}}
  </div>
</body>

<template name="slots">
  {{#each slots}}
    {{> slot}}
  {{/each}}
</template>

<template name="slot">
  <div class="slot">
    <div class="number"><span>{{number}}</span></div>
    <div class="divider"></div>
  </div>
</template>

Slot.js:

if (Meteor.is_client) {
  Template.slots.slots = function () {
    var returnArray = new Array();
    returnArray[0] = { 'number': 10 };
    returnArray[1] = { 'number': 87 };
    returnArray[2] = { 'number': 41 };
    return returnArray;
  };
}

if (Meteor.is_server) {
  Meteor.startup(function () {
    // code to run on server at startup
  });
}

J'espère que cela vous a été utile!

3
Thomas Lomas

J'utilise généralement ces deux aides de guidon:

Handlebars.registerHelper('partial', function(templateName, options) {
    return new Handlebars.SafeString(Template[templateName](options.hash));
});

Handlebars.registerHelper('partialWithContext', function(templateName, context, options) {
    var extendedContext = _.extend(context, options.hash);
    return new Handlebars.SafeString(Template[templateName](context));
});

Vous pouvez l'utiliser comme ceci (supposons que vous ayez un modèle appelé menuItem):

{{partial 'menuItem' command='Open'}}

Ou à l'intérieur d'une itération (supposons que vous ayez un modèle appelé userProfile):

{{#each regularUsers}}
    {{partialWithContext 'userProfile' . isAdmin=false}}
{{/each}}

{{#each admins}}
    {{partialWithContext 'userProfile' . isAdmin=true}}
{{/each}}

Avec les barres d'espace, vous pouvez obtenir un comportement quelque peu similaire. Dans partial.js:

Template.partialWithContext.chooseTemplate = function (name) {
    return Template[name];
};

Dans partial.html:

<template name="partialWithContext">
    {{#with chooseTemplate name}}
        {{#with ../data}}
            {{> ..}}
        {{/with}}
    {{/with}}
</template> 

Utilisez-le comme ceci:

{{#each commands}}
    {{> partialWithContext name="commandListItem" data=this isAdmin=false}}
{{/each}}
{{#each adminCommands}}
    {{> partialWithContext name="adminCommandListItem" data=this isAdmin=true}}
{{/each}}

J'espère que ça fera l'affaire.

2
Zsolt

Utilisez this lorsque vous passez un seul argument.

<div class="slot-wrapper">
    {{> slot 1}}
    {{> slot 2}}
</div>

<template name="slot">
    <div class="slot">
        <div class="number"><span>{{this}}</span></div>
        <div class="divider"></div>
    </div>
</template>

Aucun javascript requis pour le faire. Si vous avez besoin de plus d'un argument, essayez la voie de Dan.

2
Isaac Han

Ces informations sont obsolètes, les arguments de passage sont décrits en détail pour le moteur de disposition Blaze ici: https://www.discovermeteor.com/blog/spacebars-secrets-exploring-meteor-new-templating-engine/

0
Jim

beaucoup de bonnes informations ici. ma situation spécifique est que je voulais également transmettre certaines données de modèle.

je veux rendre le composant enfant Blaze réutilisable, donc toutes les données doivent être transmises. à titre d'exemple, disons que ce composant montre une note (c'est-à-dire A, B, C, etc.). sur une page, je veux utiliser le composant deux fois: votre note et la note moyenne de vos camarades de classe.

voici le composant enfant ...

Grade.html

<template name="Grade">
    <h3>{{title}}</h3>
    <div>{{grade}}</h3>
</template>

le titre peut être codé en dur dans le parent, mais la note provient de la base de données. voici comment je code le parent ...

GradePage.html

<template name="GradePage">
    {{> Grade grade=gradeYours title="Your Grade" }}
    {{> Grade grade=gradeClass title="Class Grade" }}
</template>

GradePage.js (dans la vraie vie, il est réactif, mais simplifié ici)

Template.GradePage.helpers({
    gradeYours: function () {
        return 'A-';
    },
    gradeClass: function () {
        return 'B+';
    }
});

c'est ça. le composant enfant n'a pas du tout à tendre la main pour obtenir ses valeurs.

0
zim