Wie kann das Vorhandensein einer Variablen in einer EJS-Vorlage (mit ExpressJS) überprüft werden?

121

Auf der EJS-Github-Seite gibt es nur ein einfaches Beispiel: https://github.com/visionmedia/ejs

Beispiel

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

Dies scheint die Existenz einer Variablen mit dem Namen user zu überprüfen und, falls vorhanden, einige Dinge zu tun. Duh, richtig?

Meine Frage ist, warum in aller Welt Node einen ReferenceError auslösen würde, wenn die Benutzervariable nicht existiert? Dies macht das obige Beispiel unbrauchbar. Wie kann das Vorhandensein einer Variablen angemessen überprüft werden? Wird von mir erwartet, dass ich einen Try / Catch-Mechanismus verwende und diesen ReferenceError greife?

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)

Ich verstehe, dass ich diesen Fehler beheben könnte, indem ich einfach eine lokale "Benutzer" -Variable in meinen Servercode einfüge, aber der springende Punkt hier ist, dass ich zur Laufzeit überprüfen möchte, ob solche Variablen zur Laufzeit vorhanden sind, indem ich jeden Tag if / else verwende Muster vom Typ nullcheck. Eine Ausnahme für eine Variable, die es nicht gibt, erscheint mir lächerlich.

Aashay Desai
quelle

Antworten:

149

Genauso wie Sie es mit irgendetwas in js machen würden, typeof foo == 'undefined'oder da " local " der Name des Objekts ist, das sie enthält, können Sie es tun if (locals.foo). Es ist nur roh js: p

tjholowaychuk
quelle
3
Ich frage mich, ob ich ein größeres Problem habe. Dies löst auch einen Referenzfehler aus: <% alert ('test'); %>
Aashay Desai
1
@Aashay alertist Teil des windowObjekts eines Browsers und in node.js nicht verfügbar. Die Alternative ist console.log, obwohl ich nicht weiß, ob es in einer ejs-Vorlage verfügbar ist , es sei denn, Sie geben es über weiter locals.
Zikes
2
@Zikes In diesem Fall suche ich speziell nach EJS, also auf der Browserseite. Aber wie TJ sagte, funktioniert typeof foo == 'undefined'. Ich habe gelernt, dass ich auch ein einfaches !! foo hinzufügen kann, wenn foo definiert wurde, aber null oder leer ist.
Aashay Desai
21
Gibt es dafür eine Abkürzung? Warum ehrt EJS den if (foo) -Fall nicht einfach?
Mattdlockyer
5
if (locals.user){ }FTW
s2t2
26

Versuchen Sie, die Variable mit voranzustellen locals

Beispiel: if(locals.user){}

spencer.sm
quelle
23
<% if (locals.user) { %>

 // Your logic goes here 

<% } %>
Anirudh
quelle
13

Sie können einen Ansichtshelfer erstellen, der nach "obj === void 0" sucht. Dieser ist für 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;
}

Dann benutze es in der Ansicht wie

<%- get('deep.nested.non.existent.value') %>  //returns: null
<%- get('deep.nested.non.existent.value', "default value") %> //returns: default value
Paulius Uza
quelle
3
Ich bin mir nicht sicher, warum dies abgelehnt wurde, es ist meiner Meinung nach ziemlich elegant.
Joseym
Was ist der Unterschied zwischen <%=und <%-?
NobleUplift
2
@NobleUplift Gemäß der Dokumentation unter "Tags": <%=HTML wird zuerst aus dem Wert entfernt. <%-gibt den nicht entkoppelten Wert aus. So <b>würde ein fettgedrucktes Tag bei der Verwendung werden <%-, aber einfach der Text "<b>" bei der Verwendung<%=
Matheus Avellar
Danke dir! Ich hatte keine Ahnung <% - war sogar ein gültiger Tag.
NobleUplift
13

Um zu überprüfen, ob ein Benutzer definiert ist, müssen Sie Folgendes tun:

<% if (this.user) { %>
   here, user is defined
<% } %>
HenioJR
quelle
3
Dies funktioniert nicht in der aktuellsten EJS-Bibliothek (1.0.0). Obwohl gültiges Javascript, wird EJS sich weigern, wie erwartet zu handeln.
Axoren
5
Funktioniert bei mir nicht Obwohl ich definiert habe foo, wird die else-Klausel immer noch ausgewertet. Getestet mit EJS 2.3.4 EDIT: Verwendung localsanstelle von thisArbeiten
X_Trust
8

Ich bin auf dasselbe Problem bei der Verwendung von node.js mit mongoose / express / ejs gestoßen, als ich eine Beziehung zwischen zwei Sammlungen zusammen mit mongoose's populate () herstellte. In diesem Fall existierte admins.user_id, war aber mit einem nicht vorhandenen users._id verwandt.
Also, konnte nicht finden warum:

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

fehlgeschlagen mit "Kann den Eigenschaftsnamen von null nicht lesen" Dann bemerkte ich, dass ich die Überprüfung wie folgt durchführen musste:

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

Ich musste den "Container" von "Name" überprüfen, damit es funktionierte!
Danach funktionierte das genauso:

if ( !users.user_id ) ...  

Ich hoffe es hilft.

aesede
quelle
Wie auch immer, ich kann nicht glauben, dass es so wenige offizielle Dokumentationen zu EJS gibt ... sie aktualisieren ihre Dokumentation seit 2010 nicht mehr !!!
Aesede
3

Kam auf diese Seite, um eine Antwort zu erhalten, aber ich habe mir eine kürzere Inline-Syntax dafür ausgedacht:

 <h2><%= user.name ? property.escrow.emailAddress : '' %></h2>
Adam Boostani
quelle
1
Dies ist gefährlich zu verwenden, da das Rendern von ejs fehlschlägt, wenn das Objekt 'user' keine Eigenschaft 'name' hat.
Marko Rochevski
1

Für Ihre ifAussage müssen Sie verwenden typeof:

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

<% } %>
Fabien Thetis
quelle
0

Ich übergebe einfach ein Standardobjekt, das ich 'data' = '' nenne, und übergebe es an alle meine ejs-Vorlagen. Wenn Sie echte Daten an die ejs-Vorlage übergeben müssen, fügen Sie sie als Eigenschaft des 'data'-Objekts hinzu.

Auf diese Weise wird das 'Daten'-Objekt immer definiert und Sie erhalten nie eine undefinierte Fehlermeldung, selbst wenn die Eigenschaft' Daten 'in Ihrer EJS-Vorlage, jedoch nicht in Ihrer Knoten-Express-Route vorhanden ist.

Robert Brax
quelle
0

Ich hatte das gleiche Problem und zum Glück stellte ich fest, dass es in JS auch eine Kurzschlussfunktion gibt (ich wusste, dass es eine in Ruby und einigen anderen Sprachen gibt).

Auf meiner Server- / Controllerseite (dies ist von Node.js / Express):

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

Siehst du was ich dort gemacht habe? Das &&, das nach einer möglicherweise undefinierten Variablen folgt (dh einem request.session.survey_resultObjekt, das möglicherweise Formulardaten enthält oder nicht), ist die Kurzschlussnotation in JS. Es wird nur der Teil ausgewertet, der auf das && folgt, wenn der Teil links vom && NICHT undefiniert ist. Es wird auch kein Fehler ausgegeben, wenn der linke Teil IS ist undefined. Es ignoriert es einfach.

Nun habe ich in meiner Vorlage (denken Sie daran, dass ich das req.session.survey_result_surveyObjektobjekt an meine Ansicht übergeben habe als survey_result) Felder gerendert als:

<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>

Ich habe dort auch Kurzschlüsse verwendet, nur zur sicheren Aufbewahrung.

Als ich es mit zuvor vorgeschlagenen Methoden versuchte, einfach:

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

Manchmal würde es immer noch versuchen, die Eigenschaften innerhalb der IF-Anweisung zu bewerten ... Vielleicht kann jemand eine Erklärung anbieten, warum?

Außerdem wollte ich korrigieren, dass undefinedes keine einfachen Anführungszeichen geben muss, wie ich in den vorherigen Beispielen gesehen habe. Da die Bedingung niemals ausgewertet wird true, wenn Sie einen String-Wert 'undefined'mit einem Datentyp vergleichen undefined.

Yekatjarina Aljaksandrayna Shu
quelle
0

Sie können diesen Trick verwenden:

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

Dabei ist der Bereich das übergeordnete Objekt des Benutzers

Alex Szücs
quelle
0

Wenn Sie vorhaben, dasselbe Objekt häufig zu verwenden, können Sie eine Funktion wie die folgende verwenden:

<% 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;
} %>

Verwendung:

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

Ich habe eine andere Lösung gefunden.

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

Ich hoffe das hilft.

omar
quelle