19

Still learning backbone so bear with me;

I'm trying to add a new model with blank fields to a view, but the template I've created has a whole bunch of

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

Works perfectly fine when fetching data, it populates it and all goes well. The trouble arises when I want to create a new (blank) rendered view, it gives me

Uncaught ReferenceError: some_value is not defined

I can set defaults (I do already for a few that have default values in the db) but that means typing out over 40 of them with blanks; is there a better way of handling this?

I'm fiddling around with the underscore template itself, trying something like <%= if(some_value != undefined){ some_value } %> but that also seems a bit cumbersome.

4

8 に答える 8

25

ラッパー オブジェクト内でテンプレート データを渡します。プロパティへのアクセスがなくてもエラーは発生しません。

したがって、代わりに:

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"
于 2013-03-07T23:23:49.997 に答える
13

実際、argumentsテンプレート内で使用できます。

<% if(!_.isUndefined(arguments[0].foo)) { %>
       ...
<% } %>
于 2014-05-22T13:50:40.013 に答える
10

いいえ、

アンダースコア テンプレートの実装方法が原因で、これに対する実際の修正はありません。

それについてのこの議論を見てください:

残念ながら、これは単に with(){} が JS で機能する方法です。変数が宣言されていない場合は、ReferenceError になります。テンプレートの残りの動作を維持しながら、それについてできることは何もありません。

探しているものを達成できる唯一の方法は、提案されている他の回答のようにオブジェクトを別のオブジェクトでラップするか、デフォルトを設定することです。

于 2013-03-07T23:26:17.957 に答える
0

非常に簡単な解決策: データ コレクションが正規化されていること、つまり、すべてのプロパティが各オブジェクトに存在することを確認できます (未使用の場合は null 値)。このような関数が役立ちます:

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

(注: _.zipObjectand_.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 
于 2016-02-18T15:13:21.127 に答える
0

モデルに関数を追加してテンプレートで使用することにより、@Dmitri の回答をさらに抽象化できます。

例えば:

モデル :

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

テンプレート:

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

彼の回答のコメントが示唆しているように、これはより拡張可能です。

于 2016-02-23T21:32:13.653 に答える