2013-03-07 3 views
17

Noch lernen Rückgrat, also ertragen Sie mit mir;Ignorieren von undefinierten Daten/Vars in einer Unterstrichvorlage

Ich versuche, ein neues Modell mit leeren Feldern zu einer Ansicht hinzuzufügen, aber die Vorlage habe ich erstellt hat eine ganze Reihe von

<input value="<%= some_value %>" type="whatever" /> 

Works völlig in Ordnung, wenn die Daten zu holen, es füllt sie und Alles wird Gut. Das Problem entsteht, wenn ich eine neue (leere) gerenderte Ansicht erstellen möchten, es gibt mir

Uncaught ReferenceError: some_value is not defined 

I defaults einstellen kann (ich schon für ein paar, die Standardwerte in der db haben), aber das bedeutet, die Eingabe aus über 40 von ihnen mit Leerzeichen; Gibt es einen besseren Weg, damit umzugehen?

Ich fummle mit der Unterstrich-Vorlage selbst herum und versuche so etwas wie <%= if(some_value != undefined){ some_value } %>, aber das scheint auch ein bisschen umständlich.

Antwort

8

Nein,

Es gibt keine tatsächliche fix dafür, wie Unterstreichvorlagen implementiert sind.

Siehe this discussion Informationen:

I'm afraid that this is simply the way that with(){} works in JS. If the variable isn't declared, it's a ReferenceError. There's nothing we can do about it, while preserving the rest of template behavior.

Der einzige Weg, können Sie erreichen, was Sie suchen ist, das Objekt mit einem anderen Objekt entweder zu wickeln wie die andere Antwort vorgeschlagen oder die Standardeinstellungen einrichten.

23

Übergeben Sie die Vorlage Daten in einem Wrapper-Objekt. Zugriff auf Eigenschaften fehlen keinen Fehler werfen:

Anstatt also:

var template = _.template('<%= foo %><%= bar %>'); 
var model = {foo:'foo'}; 
var result = template(model); //-> Error 

Versuchen:

var template = _.template('<%= model.foo %><%= model.bar %>'); 
var model = {foo:'foo'}; 
var result = template({model:model}); //-> "foo" 
+2

dies noch schreiben schlägt fehl, wenn Sie model.foo.bar und Bar zuzugreifen versuchen, nicht existiert – regretoverflow

+0

gut, dass Eigentum Zugang zu wissen, einen Fehler nicht werfen. Das war genau das, wonach ich suchte. Ich habe ein Objekt und es kann einige Daten enthalten. Ich wollte nur, dass es ignoriert wird, wenn es nicht da ist. – Andrei

10

Eigentlich kann man arguments innerhalb Ihrer Vorlage verwenden:

<% if(!_.isUndefined(arguments[0].foo)) { %> 
     ... 
<% } %> 
+6

yeah, viel Glück das in Millionen Orten setzen – vsync

+0

Das hat für mich funktioniert. –

4

Wenn Sie Quellcode prüfen für generierte Template-Funktion, werden Sie etwas sehen:

with (obj||{}) { 
    ... 
    // model property is used as variable name 
    ... 
} 

Was hier passiert: Zuerst versucht JS, Ihre Eigenschaft in "obj" zu finden, welches Modell ist (mehr über with Statement). Diese Eigenschaft wird im Bereich "obj" nicht gefunden. Daher durchläuft JS den globalen Gültigkeitsbereich und gibt schließlich die Ausnahme aus.

So können Sie Ihren Umfang direkt angeben, dass zu beheben:

<input value="<%= obj.some_value %>" type="whatever" /> 

Zumindest ist es für mich gearbeitet.

+1

Diese Antwort und @ Dmitriys Antwort sind die tatsächlichen Lösungen – galki

0

lodash, ein Unterstrich-Ersatz, bietet eine template Funktion mit einer integrierten Lösung. Es hat eine Option, um die Daten in ein anderes Objekt zu wickeln, um die "mit" -Anweisung zu vermeiden, die den Fehler verursacht.

Beispiel Verwendung der API-Dokumentation:

// using the `variable` option to ensure a with-statement isn’t used in the compiled template 
var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' }); 
compiled.source; 
// → function(data) { 
// var __t, __p = ''; 
// __p += 'hi ' + ((__t = (data.user)) == null ? '' : __t) + '!'; 
// return __p; 
// } 
0

Eine sehr einfache Lösung: Sie können sicherstellen, dass Ihre Datenerfassung normiert ist, das heißt, dass alle Eigenschaften in jedem Objekt vorhanden sind (mit einem Nullwert, wenn sie ungebraucht). Eine Funktion wie diese können helfen:

function normalizeCollection (collection, properties) { 
    properties = properties || []; 
    return _.map(collection, function (obj) { 
    return _.assign({}, _.zipObject(properties, _.fill(Array(properties.length), null)), obj); 
    }); 
} 

(Hinweis: _.zipObject und _.fill in neueren Versionen von lodash verfügbar sind, aber unterstreichen nicht)

Verwenden Sie es wie folgt aus:

var coll = [ 
    { id: 1, name: "Eisenstein"}, 
    { id: 2 } 
]; 

var c = normalizeCollection(coll, ["id", "name", "age"]); 
// Output => 
// [ 
// { age: null, id: 1, name: "Eisenstein" }, 
// { age: null, id: 2, name: null } 
// ] 

Natürlich Sie müssen Ihre Daten nicht permanent – nur die Funktion on the fly-Transformation aufrufen, wie Sie Ihre Template-Rendering-Funktion aufrufen:

var compiled = _.template(""); // Your template string here 
// var output = compiled(data); // Instead of this 
var output = compiled(normalizeCollection(data)); // Do this 
0

können Sie abstrakt @ Dmitri Antwort weiter durch eine Funktion zu Ihrem Modell hinzufügen und es in Ihrer Vorlage.

Zum Beispiel:

Modell:

new Model = Backbone.Model.extend({ 
    defaults: { 
     has_prop: function(prop) { 
      return _.isUndefined(this[property]) ? false : true; 
     } 
    } 
}); 

Vorlage:

<% if(has_prop('property')) { %> 
    // Property is available 
<% } %> 

Wie der Kommentar in seiner Antwort legt dies nahe, mehr erweiterbar ist.

2

Eigentlich kann man Vars wie anfängliche Objekteigenschaften zugreifen.

Wenn Sie Debugger in Vorlage aktivieren werden, können Sie finden Variable „obj“, die alle Ihre Daten enthält.

Also statt <%= title %> sollten Sie <%= obj.title %>