RandomEtc / ejs-locals

Express 3.x layout, partial and block template functions for the EJS template engine.
298 stars 63 forks source link

inserting a script tag #12

Closed ralyodio closed 11 years ago

ralyodio commented 11 years ago

How would I insert a script tag from a template with dynamic data?

In my layout I have

<%- block.scripts %>

In my page template I want to replace it with some dynamic data:

<% block('scripts', "<script> var app = window.app || {}; app.err = <%- JSON.stringify(err) %>, app.q = <%- JSON.stringify(q) %>; </script>") -%>

I get an error:

500 SyntaxError: Unexpected token % -- i'm assuming because I can't do <%= JSON.stringigy(err) %> here.

RandomEtc commented 11 years ago

This is definitely a weak area in this library right now. It really needs more work in the parser to handle blocks better (like dust, jade or swig do).

Here's the workaround, which is not pretty:

<%

block('scripts',"<script>\n\
$(function(){\n\
  // your js here, with double quotes escaped \" and explicit newlines followed by a \ e.g. \n\
});\n\
</script>\n");

%>

If I was going to start supporting things like this more seriously I'd probably fork ejs and back-port these locals there first, and then work directly on the parser. I'm not planning to do that work myself right now but I'll happily help test if you decide to take it on.

ralyodio commented 11 years ago

But how do I use an ejs variable inbetween the script tags? <%= foo %> throws an error.

RandomEtc commented 11 years ago

Yeah, this is a mess, sorry. You should be able to close the double quotes and append your ejs variable though, e.g. "+foo+" ... but that's a hack. If that's really what you need then be very careful. The way scripts are inserted is not escaped. I would personally put the variable in the markup, safely escaped, and have the script pick it up from there.

ralyodio commented 11 years ago

I can't put my script block in a js file, because I'm setting session data into a variable which I need from the page template.

So my app.js file will read the variable set on the page script var sess = <%= session %>; /script that I have to put below the app.js include file in layout.ejs, I was trying to do this with a block in layout.ejs

I wll try terminating string with quote.

ralyodio commented 11 years ago

I don't know how difficult this would be to do, but here's a demonstration of what I'm trying to accomplish:

http://pastie.org/4782689

The suggestion you made works, but would have to repeated in every template to get it below the included app.js library in layout.ejs.

RandomEtc commented 11 years ago

OK, I see. I've never needed to pass variables from server-side to client-side js this way but I see why you're doing it.

The layout should have access to the local variables though. If you're including it on every page, why not include it in the layout like this?

<body>
    <script src="/static/app.js"></script>
    <%- blocks.script %>
    <script>
      app.req.err = <%- JSON.stringify(err) %>;
      app.req.q = <%- JSON.stringify(q) %>;
    </script>
  </body>

Otherwise I'm not sure what to suggest. It's probably worth moving to a more sophisticated template library. Dust and Swig both look good and should be faster than EJS too. If you're using Express 3 then use https://github.com/visionmedia/consolidate.js to experiment with different template formats.

Sorry I don't have a better answer!

RandomEtc commented 11 years ago

Oh, you can also just include the script tag anywhere in the page. If all it does is set variables it shouldn't cause a problem, and it should run before ondomready.

ralyodio commented 11 years ago

Yeah, i guess I didn't think of that...I figured there was an easier way. I looked into dustjs-linkedin plugin, but I could not get the layouts to work with partials. Here's the StackOverflow question about the problem I had: http://stackoverflow.com/questions/12489739/using-dustjs-linkedin-templates-in-node-js-and-express3-x

./views/test1.dust

{+base.dust/} {<main} Child Content {/main}

500 Error: Cannot find module 'dust'