2012-01-02 13 views
91

Tengo problemas con una variable (config) declarada en un archivo de plantilla de jade (index.jade) que no se pasa a un archivo javascript, lo que hace que mi javascript se cuelgue. Aquí está el archivo (vistas/index.jade):¿Cómo pasar una variable de un archivo de plantilla de jade a un archivo de script?

h1 #{title} 

script(src='./socket.io/socket.io.js') 
script(type='text/javascript') 
    var config = {}; 
    config.address = '#{address}'; 
    config.port = '#{port}'; 
script(src='./javascripts/app.js') 

Aquí está una parte de mis app.js (lado del servidor):

app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(app.router); 
    app.use(express.static(__dirname + '/public')); 
}); 

app.configure('development', function(){ 
    app.set('address', 'localhost'); 
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
}); 

app.configure('production', function(){ 
    app.use(express.errorHandler()); 
}); 

// Routes 

app.get('/', function(req, res){ 
    res.render('index', { 
    address: app.settings.address, 
    port: app.settings.port 
}); 
}); 

if (!module.parent) { 
    app.listen(app.settings.port); 
    console.log("Server listening on port %d", 
app.settings.port); 
} 

// Start my Socket.io app and pass in the socket 
require('./socketapp').start(io.listen(app)); 

Y aquí está una parte de mi archivo javascript que (accidentes/javascripts/app.js públicas):

(function() { 
     var socket = new io.Socket(config.address, {port: config.port, rememberTransport: false}); 

estoy ejecutando el sitio en el modo de desarrollo (= NODE_ENV desarrollo) en el servidor local (mi propia máquina). Estoy usando node-inspector para la depuración, que me dijo que la variable de configuración no está definida en public/javascripts/app.js.

¿Alguna idea? ¡¡Gracias!!

+0

posible duplicación de [ExpressJS Pass variables a JavaScript] (http://stackoverflow.com/questions/9268951/expressjs-pass-variables-to-javascript) – laggingreflex

Respuesta

134

Es un poco tarde, pero ...

script. 
    loginName="#{login}"; 

Esto está trabajando muy bien en mi guión . En Express, estoy haciendo esto:

exports.index = function(req, res){ 
    res.render('index', { layout:false, login: req.session.login }); 
}; 

supongo que la última jade es diferente?

Merc.

editar: añadido "." después de la secuencia de comandos para evitar la advertencia de Jade.

+1

¡Gracias por aceptar la respuesta! Entonces, ¿cuál fue el problema _actual_ con tu código? – Merc

+0

Sí, hice que esto funcionara también envolviendo la variable local en la plantilla entre comillas y el indicador # {}. – Askdesigners

+0

Esta respuesta es peligrosa, la respuesta de lagginreflex codifica correctamente la cadena (las nuevas líneas en el nombre de inicio de sesión podrían permitir la ejecución del código). –

2

Ver esta pregunta: JADE + EXPRESS: Iterating over object in inline JS code (client-side)?

estoy teniendo el mismo problema. Jade no pasa variables locales en (o hace ninguna plantilla en absoluto) a las secuencias de comandos de JavaScript, simplemente pasa todo el bloque en texto literal. Si usa las variables locales 'dirección' y 'puerto' en su archivo Jade encima de la etiqueta del script, deberían aparecer.

soluciones posibles se enumeran en la pregunta he vinculado al anterior, pero puede: - pass cada línea de texto sin escape (= al comienzo de cada línea!), Y en pocas palabras "-" antes de cada línea de javascript que usa una variable local, o: - Pasa las variables a través de un elemento dom y accede a través de JQuery (feo)

¿No hay una mejor manera? Parece que los creadores de Jade no quieren de varias líneas de soporte javascript, como lo demuestra este hilo en GitHub: https://github.com/visionmedia/jade/pull/405

78

!{} es para unescaped code interpolación, lo que es más adecuado para objetos

script var data = !{JSON.stringify(data).replace(/<\//g, '<\\/')} 

{ foo: 'bar' } 
// becomes: 
<script>var data = {"foo":"bar"}</script> 

{ foo: 'bar</script><script>alert("xss")//' } 
// becomes: 
<script>var data = {"foo":"bar<\/script><script>alert(\"xss\")//"}</script> 

La idea es evitar que el atacante:

  1. salir de la variable: JSON.stringify Escapes las comillas
  2. Salto de la etiqueta de secuencia de comandos: si la variable co ntents (que es posible que no pueda controlar si proviene de la base de datos por ej.) Tiene una cadena </script>, la declaración reemplazar cuidará de que

https://github.com/pugjs/pug/blob/355d3dae/examples/dynamicscript.pug


#{} es para string interpolation escapado, que es adecuado sólo si se trabaja con cadenas. Se no funciona con objetos

script var data = #{JSON.stringify(data)} 

//=> <script>var data = {&quot;foo&quot;:&quot;bar&quot;}</script> 
+1

¡Muchas gracias! – Sgnl

+0

¡Excelente respuesta! He estado buscando este tema durante más de 20 minutos y ninguna otra respuesta indicó la diferencia entre! {} Y # {}. ¡Todo este tiempo, pensé! {] Era el equivalente obsoleto de # {} ... Gracias de nuevo. –

+0

Muchas gracias !! –

0

Así es como me dirigí a esta (usando un derivado de media)

Mis variables:

{ 
    NODE_ENV : development, 
    ... 
    ui_varables { 
    var1: one, 
    var2: two 
    } 
} 

Primero tenía que asegurarse de que el necesario las variables de configuración se estaban pasando. MEAN usa el paquete node nconf y, de forma predeterminada, está configurado para limitar qué variables pasan del entorno. Tenía que poner remedio que:

config/config.js:

el original:

nconf.argv() 
    .env(['PORT', 'NODE_ENV', 'FORCE_DB_SYNC']) // Load only these environment variables 
    .defaults({ 
    store: { 
    NODE_ENV: 'development' 
    } 
}); 

después de las modificaciones:

nconf.argv() 
    .env('__') // Load ALL environment variables 
    // double-underscore replaces : as a way to denote hierarchy 
    .defaults({ 
    store: { 
    NODE_ENV: 'development' 
    } 
}); 

Ahora puedo establecer mis variables de la siguiente manera:

export ui_varables__var1=first-value 
export ui_varables__var2=second-value 

Nota: Restablecí el "indicador de jerarquía" a "__" (doble guión bajo) porque su valor predeterminado era ":", lo que hace que las variables sean más difíciles de configurar desde bash. Ver otra publicación en este hilo.

Ahora la parte de jade: A continuación, deben renderizarse los valores, para que javascript pueda recogerlos en el lado del cliente. Una forma sencilla de escribir estos valores en el archivo de índice. Como esta es una aplicación de una página (angular), esta página siempre se carga primero. Creo que idealmente debería ser un archivo de inclusión de JavaScript (solo para mantener las cosas limpias), pero esto es bueno para una demostración.

app/controllers/index.js:

'use strict'; 
var config = require('../../config/config'); 

exports.render = function(req, res) { 
    res.render('index', { 
    user: req.user ? JSON.stringify(req.user) : "null", 
    //new lines follow: 
    config_defaults : { 
     ui_defaults: JSON.stringify(config.configwriter_ui).replace(/<\//g, '<\\/') //NOTE: the replace is xss prevention 
    } 
    }); 
}; 

app/views/index.jade:

extends layouts/default 

block content 
    section(ui-view) 
    script(type="text/javascript"). 
    window.user = !{user}; 
    //new line here 
    defaults = !{config_defaults.ui_defaults}; 

En mi HTML representado, esto me da un pequeño guión :

<script type="text/javascript"> 
window.user = null;   
defaults = {"var1":"first-value","var2:"second-value"}; 
</script>   

De este punto es fácil para angular utilizar el código.

+0

Esta es una manera muy larga de decir lo que la respuesta aceptada ya dice. Además, mencionar MEAN, nconf, etc. son irrelevantes. La pregunta es acerca de cómo pasar variables al cliente, no sobre cómo hizo su pila de desarrollo. Sin embargo, no bajamos, ya que todavía hace mucho esfuerzo en esta respuesta. – Mrchief

+0

demasiado complicado – andygoestohollywood

Cuestiones relacionadas