2012-06-06 12 views
64

Curioso si estoy haciendo esto bien y si no es así como ustedes se acercarían a esto.Accediendo a las variables locales Express.js en el lado del cliente JavaScript

Tengo una plantilla de Jade que necesita representar algunos datos recuperados de una base de datos MongoDB y también necesito tener acceso a esos datos dentro de un archivo JavaScript del lado del cliente.

estoy usando Express.js y enviar los datos a la plantilla del jade de la siguiente manera:

var myMongoDbObject = {name : 'stephen'}; 
res.render('home', { locals: { data : myMongoDbObject } }); 

A continuación, en el interior de home.jade Puedo hacer cosas como:

p Hello #{data.name}! 

Que escribe:

Hello stephen! 

Ahora lo que quiero es als o tener acceso a este objeto de datos dentro de un archivo JS del lado del cliente para poder manipular el objeto, por ejemplo, hacer clic en un botón antes de volver a enviarlo al servidor para actualizar la base de datos.

He podido lograr esto guardando el objeto "datos" dentro de un campo de entrada oculto en la plantilla de Jade y luego obteniendo el valor de ese campo dentro de mi archivo JS del lado del cliente.

Dentro home.jade

- local_data = JSON.stringify(data) // data coming in from Express.js 
input(type='hidden', value=local_data)#myLocalDataObj 

Luego, en mi cliente archivo JS lado puedo acceder local_data así:

interior myLocalFile.js

var localObj = JSON.parse($("#myLocalDataObj").val()); 
console.log(localObj.name); 

Sin embargo, esta el negocio de stringify/parsing se siente desordenado. Sé que puedo vincular los valores de mi objeto de datos a objetos DOM en mi plantilla de Jade y luego obtener esos valores usando jQuery, pero me gustaría tener acceso al Objeto real que regresa de Express en mi lado del cliente JS.

¿Es mi solución óptima? ¿Cómo pueden lograr esto?

+3

realidad he creado un paquete de NPM hace un par de meses para resolver este problema exacto: https://github.com/brooklynDev/JShare – BFree

Respuesta

69

Cuando se realiza el renderizado, solo el HTML renderizado se envía al cliente. Por lo tanto, no habrá más variables disponibles. Lo que podría hacer, en lugar de escribir es el objeto en la salida del elemento de entrada del objeto como JavaScript prestados:

script(type='text/javascript'). 
    var local_data =!{JSON.stringify(data)} 

EDIT: Al parecer Jade requiere un punto después del primer paréntesis de cierre.

+0

estoy sigue viendo "datos" como indefinido dentro de la etiqueta de script. – braitsch

+0

¡Por favor vea mi código editado! ¡Simplemente probé y funcionó! – Amberlamps

+0

Ok, esto es mejor que mi solución de campo de entrada ya que no requiere analizar la cadena JSON de nuevo en un objeto o buscar el valor del campo de entrada con jQuery. – braitsch

2

¿Has oído hablar de socket.io? (http://socket.io/). Una manera fácil de acceder al objeto desde express sería abrir un socket entre node.js y su javascript. De esta forma, los datos pueden pasarse fácilmente al lado del cliente y luego manipularse fácilmente mediante javascript. El código no debería ser demasiado, simplemente un socket.emit() de node.js y un socket.on() del cliente. ¡Creo que sería una solución efectiva!

+15

Esto está usando martillo para golpear a una abeja. Agrega muchas solicitudes de casi nada. –

+0

Exactamente, Socket.io es excesivo en este caso. Estoy buscando la forma más ligera de transportar variables JS desde el servidor a un script del lado del cliente. – braitsch

+3

LOL, me gusta un poco lo que Alex sugiere, ¡bam! ah todos esos locales molestos bam bam! – user1323136

13

Lo hago un poco diferente.En mi controlador de hago esto:

res.render('search-directory', { 
    title: 'My Title', 
    place_urls: JSON.stringify(placeUrls), 
}); 

Y luego en el Javascript en mi archivo de jade lo uso como esto:

var placeUrls = !{place_urls}; 

En este ejemplo se utiliza para el gorjeo de arranque plug-in de escritura siguiente. A continuación, puede usar algo como esto para analizar si es necesario:

jQuery.parseJSON(placeUrls); 

Nótese también que se puede dejar de lado los locales: {}.

+0

+1 en la nota sobre dejar afuera a los lugareños, no sabía que podrías hacer eso. – braitsch

+0

¿Qué significa * dejar de lado a los lugareños *? @braitsch – iamrudra

+0

@iamrudra No es necesario preceder al objeto locals en la función de representación con la palabra "locales". '' res.render ('home', {{data: myObject}}) '' está bien contra '' res.render ('home', {locals: {data: myObject}}) '' aunque podría sugerirle hacerlo de todos modos por el bien de la claridad. – braitsch

1

El uso de plantillas de Jade:

Si va a insertar @Amberlamps fragmento de código por encima de un archivo HTML estático incluido, recuerde especificar !!! 5 en la parte superior, para evitar tener roto su estilo, en vistas/index.jade:

!!! 5 
script(type='text/javascript') 
    var local_data =!{JSON.stringify(data)} 

include ../www/index.html 

Esto pasará en su variable de local_data antes de que las cargas de página HTML estática reales, por lo que la variable es disponible globalmente desde el comienzo.

Serverside (usando Jade motor de plantillas) - server.js:

app.set('views', __dirname + '/views'); 
app.set('view engine', 'jade'); 

app.get('/', ensureAuthenticated, function(request, response){ 
    response.render('index', { data: {currentUser: request.user.id} }); 
}); 

app.use(express.static(__dirname + '/www')); 
1

No es necesario pasar las variables locales en hacer llamadas, las variables locales son globales. En su llamada de archivo pug no ponga la expresión de las teclas, por ejemplo, #{}. Sólo tiene que utilizar algo como: base(href=base.url)

donde base.url es app.locals.base = { url:'/' };

Cuestiones relacionadas