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.

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


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){}


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

 // Your logic goes here 

<% } %>

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

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

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.


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>

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) { %>

<% } %>

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.


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.


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


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

0

Ich habe eine andere Lösung gefunden.

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

Ich hoffe das hilft.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.