Quelle est la bonne façon de vérifier l'existence d'une variable dans un modèle EJS (à l'aide d'ExpressJS)?


122

Sur la page github EJS, il y a un et un seul exemple simple: https://github.com/visionmedia/ejs

Exemple

<% if (user) { %>
    <h2><%= user.name %></h2>
<% } %>

Cela semble vérifier l'existence d'une variable nommée user, et si elle existe, faites certaines choses. Duh, non?

Ma question est, pourquoi dans le monde Node lancerait-il une ReferenceError si la variable utilisateur n'existe pas? Cela rend l'exemple ci-dessus inutile. Quelle est la manière appropriée de vérifier l'existence d'une variable? Dois-je utiliser un mécanisme try / catch et récupérer cette ReferenceError?

ReferenceError: user is not defined
    at IncomingMessage.anonymous (eval at <anonymous> (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:140:12))
    at IncomingMessage.<anonymous> (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:142:15)
    at Object.render (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:177:13)
    at ServerResponse.render (/usr/local/lib/node/.npm/express/1.0.7/package/lib/express/view.js:334:22)
    at Object.<anonymous> (/Users/me/Dropbox/Projects/myproject/server.js:188:9)
    at param (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:146:21)
    at pass (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:162:10)
    at /usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:152:27
    at Object.restrict (/Users/me/Dropbox/Projects/myproject/server.js:94:5)
    at param (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:146:21)

Je comprends que je pourrais faire disparaître cette erreur en ajoutant simplement une variable locale "utilisateur" dans mon code serveur, mais le point essentiel ici est que je veux vérifier l'existence de telles variables au moment de l'exécution en utilisant votre tous les jours si / sinon modèle de type nullcheck. Une exception pour une variable qui n'existe pas me semble ridicule.

Réponses:


149

De la même manière que vous le feriez avec n'importe quoi dans js, typeof foo == 'undefined'ou puisque "locals" est le nom de l'objet qui les contient, vous pouvez le faire if (locals.foo). C'est juste brut js: p


3
Je commence à me demander si j'ai un plus gros problème entre les mains. Cela génère également une erreur de référence: <% alert ('test'); %>
Aashay Desai

1
@Aashay alertfait partie d'un windowobjet de navigateur et n'est pas disponible dans node.js. L'alternative est console.log, même si je ne sais pas si elle est disponible dans un modèle ejs à moins que vous ne la transmettiez via locals.
Zikes

2
@Zikes Dans ce cas, je recherche spécifiquement EJS, donc c'est sur la page du navigateur. Mais, comme TJ l'a dit, typeof foo == 'undefined' fonctionne. J'ai appris que je pourrais aussi ajouter un simple !! foo si foo a été défini mais est nul ou vide.
Aashay Desai

21
Y a-t-il un raccourci pour cela? Pourquoi EJS n'honore-t-il pas simplement le cas if (foo)?
mattdlockyer

5
if (locals.user){ }FTW
s2t2

26

Essayez de faire précéder la variable de locals

Exemple: if(locals.user){}


23
<% if (locals.user) { %>

 // Your logic goes here 

<% } %>

13

Vous pouvez créer un assistant de vue qui vérifie "obj === void 0", celui-ci est pour express.js:

res.locals.get = function() {
    var args = Array.prototype.slice.call(arguments, 0);
    var path = args[0].split('.');
    var root = this;
    for (var i = 0; i < path.length; i++) {
        if(root[path[i]] === void 0) {
            return args[1]?args[1]:null;
        } else {
            root = root[path[i]];
        }
    };
    return root;
}

Ensuite, utilisez-le dans la vue comme

<%- get('deep.nested.non.existent.value') %>  //returns: null
<%- get('deep.nested.non.existent.value', "default value") %> //returns: default value

3
Je ne sais pas pourquoi cela a été critiqué, c'est plutôt élégant à mon avis.
joseym

Quelle est la différence entre <%=et <%-?
NobleUplift

2
@NobleUplift Selon la documentation , sous "Tags": <%=HTML échappe d'abord la valeur; <%-renvoie la valeur non échappée. Donc <b>deviendrait une balise en gras lors de l'utilisation <%-, mais simplement le texte "<b>" lors de l'utilisation<%=
Matheus Avellar

Je vous remercie! Je n'avais aucune idée de <% - était même une balise valide.
NobleUplift

13

Pour vérifier si l'utilisateur est défini, vous devez le faire:

<% if (this.user) { %>
   here, user is defined
<% } %>

3
Cela ne fonctionne pas dans la bibliothèque EJS la plus à jour (1.0.0). Bien que JavaScript soit valide, EJS refusera d'agir comme prévu.
Axoren

5
Ça ne marche pas pour moi. Même si j'ai défini foo, la clause else est toujours évaluée. Testé avec EJS 2.3.4 EDIT: utilisation localsà la place des thistravaux
X_Trust

8

J'ai rencontré le même problème en utilisant node.js avec mangouste / express / ejs lors de la création d'une relation entre 2 collections avec populate () de mangouste, dans ce cas admins.user_id existait mais était lié à un user._id inexistant.
Donc, je n'ai pas pu trouver pourquoi:

if ( typeof users.user_id.name == 'undefined' ) ...

échouait avec "Impossible de lire la propriété 'nom' de null" Ensuite, j'ai remarqué que je devais faire la vérification comme ceci:

if ( typeof users.user_id == 'undefined' ) ...

J'avais besoin de vérifier le "conteneur" de 'nom', donc ça a marché!
Après cela, cela a fonctionné de la même manière:

if ( !users.user_id ) ...  

J'espère que ça aide.


Bref, je ne peux pas croire qu'il y ait si peu de documentation officielle sur EJS ... ils ne mettent pas à jour leur documentation depuis 2010 !!!
aesede le

3

Je suis venu sur cette page pour obtenir une réponse, mais j'ai proposé une syntaxe en ligne plus courte, à savoir:

 <h2><%= user.name ? property.escrow.emailAddress : '' %></h2>

1
Ceci est dangereux à utiliser, car si l'objet 'user' n'a pas de propriété 'name', le rendu ejs échouera.
Marko Rochevski

1

Pour votre ifrelevé, vous devez utiliser typeof:

<% if (typeof user == 'object' && user) { %>

<% } %>

0

Ce que je fais, c'est juste passer un objet par défaut que j'appelle 'data' = '' et le passer à tous mes modèles ejs. Si vous avez besoin de transmettre des données réelles au modèle ejs, ajoutez-les en tant que propriété de l'objet 'data'.

De cette façon, l'objet 'data' est toujours défini et vous n'obtenez jamais de message d'erreur indéfini, même si la propriété 'data' existe dans votre modèle ejs mais pas dans votre route express de nœud.


0

J'ai eu le même problème, et heureusement, j'ai trouvé qu'il y avait aussi une fonction de court-circuit dans JS (je savais qu'il y en avait une en Ruby et dans d'autres langues).

Du côté de mon serveur / contrôleur (cela vient de Node.js / Express):

return res.render('result', {survey_result : req.session.survey_result&&req.session.survey_result.survey }); 

Regarde ce que j'ai fait là? Le && qui suit une variable éventuellement indéfinie (c'est-à-dire un request.session.survey_resultobjet, qui pourrait ou non avoir des données de forme) est la notation de court-circuit dans JS. Il évalue uniquement la partie qui suit le && si la partie à gauche du && n'est PAS indéfinie. Il ne génère pas non plus d'erreur lorsque la partie gauche EST undefined. Il l'ignore tout simplement.

Maintenant, dans mon modèle (rappelez-vous que j'ai passé l'objet req.session.survey_result_surveyobjet à ma vue en tant que survey_result), puis j'ai rendu les champs comme:

<table>
    <tr>
        <td> Name:</td>
        <td> <%=survey_result&&survey_result.name%></td>
    </tr>
    <tr>
        <td> Dojo Location:</td>
        <td> <%=survey_result&&survey_result.dojo_loc%></td>
    </tr>
    <tr>
        <td> Favourite Language:</td>
        <td> <%=survey_result&&survey_result.fave_lang%></td>
    </tr>

J'ai utilisé le court-circuit là aussi, juste pour la sécurité.

Lorsque je l'ai essayé avec les méthodes suggérées précédemment, il suffit de:

<% if (typeof survey_result !== undefined) { %>
... <!-- some js and/or html code here -->
<% } %>

Parfois, il essayait toujours d'évaluer les propriétés dans l'instruction IF ... Peut-être que quelqu'un peut offrir une explication sur pourquoi?

En outre, je voulais corriger cela undefineddoit être sans les guillemets simples, comme je l'ai vu dans les exemples précédents. Parce que la condition ne sera jamais évaluée true, car vous comparez une valeur String 'undefined'avec un type de données undefined.


0

Vous pouvez utiliser cette astuce:

user.name // stops code execution,if user is undefined
(scope.user||0).name // === undefined

où scope est l'objet parent de l'utilisateur


0

si vous prévoyez d'utiliser souvent le même objet, vous pouvez utiliser une fonction comme celle-ci:

<% function userObj(obj){
    //replace user with what you name your object
    if(typeof user === 'object'){
        let result = user;
        if(obj){
            obj = obj.split('.');
            for(let i = 0; i < obj.length; i++){
                if(obj[i] && obj[i].trim() !== '' && result[obj[i]]){
                    result = result[obj[i]];
                }else{
                    result = false;
                    break;
                }
            }
        }
        return result;
    }
    return false;
} %>

usage:

<% if(userObj('name')){
    <h2><%= userObj('name') %></h2>
} %>

0

J'ai trouvé une autre solution.

<% if(user){ %>
   <% if(user.name){ %>
     <h1><%= user.name %></h1>
<%}}%>

J'espère que ça aide.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.