2013-03-07 5 views
17

अभी भी रीढ़ की हड्डी सीखना मेरे साथ सहन करना;अंडरस्कोर टेम्पलेट में अपरिभाषित डेटा/वर्र्स को अनदेखा करना

मैं एक दृश्य को खाली क्षेत्र के साथ नए मॉडल जोड़ने के लिए कोशिश कर रहा हूँ, लेकिन मैं बना लिया है टेम्पलेट

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

वर्क्स बिल्कुल ठीक जब डेटा प्राप्त करने में की एक पूरी गुच्छा है, यह यह भरता है और सब अच्छा होता है। मुसीबत पैदा होती है जब मैं एक नया (खाली) गाया दृश्य बनाना चाहते हैं, यह मेरे

Uncaught ReferenceError: some_value is not defined 

मैं defaults सेट कर सकते हैं (मैं पहले से ही कुछ DB में मूलभूत मूल्यों है कि के लिए करते हैं) देता है, लेकिन है कि पूरा लिखने का मतलब उनमें से 40 से अधिक रिक्त स्थान के साथ; क्या इसे संभालने का एक बेहतर तरीका है?

मैं अंडरस्कोर टेम्पलेट के साथ खुद को झुका रहा हूं, <%= if(some_value != undefined){ some_value } %> जैसे कुछ कोशिश कर रहा हूं लेकिन यह थोड़ा बोझिल लगता है।

उत्तर

8

नहीं है,

कोई वास्तविक ठीक है इसके लिए अंडरस्कोर टेम्पलेट्स को लागू करने के तरीके के कारण।

इसके बारे में this discussion देखें:

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.

एक ही तरीका है कि आप पूरा कर सकते हैं क्या आप या तो किसी अन्य वस्तु के साथ वस्तु रैप करने के लिए अन्य उत्तर की तरह का सुझाव दिया है के लिए देख रहे हैं, या चूक की स्थापना।

23

एक रैपर ऑब्जेक्ट के अंदर टेम्पलेट डेटा पास करें। बजाय,

तो: संपत्ति का उपयोग कर सकते लापता एक त्रुटि फेंक नहीं होगा

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

प्रयास करें:

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

यह अभी भी विफल रहता है अगर आप model.foo.bar का उपयोग करने की कोशिश करते हैं और बार – regretoverflow

+0

अच्छा मौजूद नहीं है कि संपत्ति का उपयोग एक त्रुटि फेंक नहीं होगा पता करने के लिए लिखना चाहिए। यह ठीक वही है जिसकी मुझे तलाश थी। मेरे पास एक वस्तु है और इसमें कुछ डेटा हो सकता है। मैं बस इसे अनदेखा करना चाहता था अगर यह वहां नहीं है। – Andrei

10

वास्तव में, आप अपने टेम्पलेट के अंदर arguments उपयोग कर सकते हैं:

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

यहां होता:

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

हाँ, अच्छी किस्मत यह है कि लाखों स्थानों में – vsync

+0

यह मेरे लिए काम किया। –

4

आप उत्पन्न टेम्पलेट समारोह के लिए स्रोत कोड की जांच, तो आप कुछ इस तरह देखेंगे: पहले जेएस आपकी संपत्ति को "obj" में ढूंढने का प्रयास करता है, जो मॉडल है (with कथन के बारे में अधिक)। यह संपत्ति "obj" दायरे में नहीं मिली है, इसलिए जेएस वैश्विक दायरे तक ऊपर और ऊपर जाता है और अंत में अपवाद फेंकता है।

तो, आपको लगता है कि ठीक करने के लिए सीधे अपने दायरे निर्दिष्ट कर सकते हैं:

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

कम से कम यह मेरे लिए काम किया।

+1

यह उत्तर और @ दिमित्री का जवाब वास्तविक समाधान हैं – galki

0

अंडरस्कोर प्रतिस्थापन लॉनाश, अंतर्निहित समाधान के साथ template फ़ंक्शन प्रदान करता है। इसमें त्रुटि के कारण "साथ" कथन से बचने के लिए डेटा को किसी अन्य ऑब्जेक्ट में लपेटने का विकल्प होता है।API दस्तावेज़ों से

नमूना उपयोग:

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

एक बहुत ही सरल समाधान: यदि आप सुनिश्चित कर सकते हैं कि आप अपने डेटा संग्रहण सामान्यीकृत है, यानी कि सभी गुण प्रत्येक वस्तु में मौजूद हैं (एक शून्य मान के साथ करता है, तो वे कर रहे हैं अप्रयुक्त)। इस तरह एक समारोह में मदद कर सकते हैं:

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

(नोट: _.zipObject और _.fill lodash के हाल के संस्करणों में उपलब्ध हैं, लेकिन रेखांकित नहीं)

इस तरह यह प्रयोग करें:

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 } 
// ] 
बेशक

, आपको अपने डेटा को स्थायी रूप से बदलना नहीं है – बस फ्लाई पर फ़ंक्शन को आमंत्रित करें क्योंकि आप अपना टेम्पलेट प्रतिपादन फ़ंक्शन कॉल करते हैं:

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

आप अपने मॉडल में एक फ़ंक्शन जोड़कर और अपने टेम्पलेट में इसका उपयोग करके @ दिमित्री के उत्तर को आगे बढ़ा सकते हैं।

उदाहरण के लिए:

मॉडल:

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

टेम्पलेट:

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

उसके जवाब में टिप्पणी से पता चलता है यह अधिक बढ़ाई है।

2

दरअसल, आप प्रारंभिक ऑब्जेक्ट गुणों जैसे वर्रों तक पहुंच सकते हैं।

यदि आप टेम्पलेट में डीबगर सक्रिय करेंगे, तो आप चर "obj" पा सकते हैं, जिसमें आपका सभी डेटा शामिल है।

बजाय <%= title %> की आप <%= obj.title %>

संबंधित मुद्दे