template literal es6 concatenar backstick javascript backbone.js underscore.js

javascript - literal - Ignorar datos/vars no definidos en una plantilla de subrayado



template javascript (8)

Todavía aprendiendo espinazo así que tengan paciencia conmigo;

Estoy tratando de agregar un nuevo modelo con campos en blanco a una vista, pero la plantilla que he creado tiene un montón de

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

Funciona perfectamente bien al obtener datos, los rellena y todo va bien. El problema surge cuando quiero crear una nueva vista renderizada (en blanco), me da

Uncaught ReferenceError: some_value is not defined

Puedo establecer defaults (ya lo hago para algunos que tienen valores predeterminados en la base de datos) pero eso significa escribir más de 40 de ellos con espacios en blanco; ¿Hay una mejor manera de manejar esto?

Estoy jugueteando con la plantilla de guión bajo, intentando algo como <%= if(some_value != undefined){ some_value } %> pero eso también parece un poco incómodo.


En realidad, puede acceder a vars como propiedades de objetos iniciales.

Si activa el depurador en la plantilla, puede encontrar la variable "obj", que contiene todos sus datos.

Así que en lugar de <%= title %> debes escribir <%= obj.title %>


En realidad, puedes usar arguments dentro de tu plantilla:

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


Pase los datos de la plantilla dentro de un objeto contenedor. Falta de acceso a la propiedad no arrojará un error:

Entonces, en lugar de:

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

Tratar:

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


Puede abstraer más la respuesta de @Dmitri agregando una función a su modelo y usándola en su plantilla.

Por ejemplo:

Modelo:

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

Modelo:

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

Como el comentario en su respuesta sugiere que esto es más extensible.


Si verifica el código fuente para la función de plantilla generada, verá algo como esto:

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

Lo que sucede aquí: al principio JS intenta encontrar su propiedad en "obj", que es modelo (más acerca with declaración). Esta propiedad no se encuentra en el alcance "obj", por lo que JS se desplaza hasta el alcance global y finalmente lanza la excepción.

Entonces, puedes especificar tu alcance directamente para arreglar eso:

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

Al menos funcionó para mí.


Una solución muy simple: puede asegurarse de que su recopilación de datos esté normalizada, es decir, que todas las propiedades estén presentes en cada objeto (con un valor nulo si no se utilizan). Una función como esta puede ayudar:

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

(Nota: _.zipObject y _.fill están disponibles en versiones recientes de lodash pero no subrayan)

Úsalo así:

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

Por supuesto, no tiene que transformar sus datos de forma permanente, simplemente invoque la función sobre la marcha al llamar a la función de representación de la plantilla:

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


lodash, un reemplazo de subrayado, proporciona una función de template con una solución integrada. Tiene la opción de envolver los datos en otro objeto para evitar la declaración "con" que causa el error.

Ejemplo de uso de la documentación de la 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; // }


No,

No hay una solución real para esto debido a la forma en que se implementan las plantillas de subrayado.

Vea esta discusión al respecto:

Me temo que esta es simplemente la forma en que funciona con () {} en JS. Si la variable no está declarada, es un error de referencia. No hay nada que podamos hacer al respecto, al tiempo que conservamos el resto del comportamiento de la plantilla.

La única forma en que puede lograr lo que está buscando es envolver el objeto con otro objeto como la otra respuesta sugerida, o configurar los valores predeterminados.