1

Alright, so my question is very basic. I'm using Node.js with Underscore as the registered templating engine, using the Expressjs framework. I'm trying to create partials. I want to be able to do something like what you do with other languages:

<% include('header') %>
    <body id="content">
        <span>Blah</span>
    </body>

<% include('footer') %>

You get the idea. So, does anyone know of a way to make this possible using underscore on Node?

EDIT:

<%
var isReturned = false;
var isSuccess = false;
if(typeof user != 'undefined'){
    var isReturned = true;
}
if(typeof errors == 'undefined'){
    var errors = null;
}

if(typeof success != 'undefined'){
    isSuccess = true;
}
%>
<% _.template('header') %>
    <h1><%= title %></h1>
    <% if(isSuccess){ %>
        <div style="background-color: green; border: 1px solid black; color: white; width: auto; display: inline-block; padding: 0.5em; border-radius: 5px;">You have successfully registered! <a href="/login">Click Here</a> to login.</div>
    <% } %>
    
    <form id="register" name="register" action="/register" method="POST">
        <table>
            <tr>
                <td>
                    <label for="firstName">First Name:</label>
                </td>
                <td>
                    <input type="text" size=15 name="firstName" value="<% if(isReturned){ %> <%= user.firstName %> <% } %>"/>
                </td>
                <% if(errors != null && typeof errors.firstName !== 'undefined' && errors.firstName !== null){ %>
                    <td class="error"><%= errors.firstName.msg %></td>
                <% } %>
            </tr>
            <tr>
                <td>
                    <label for="lastName">Last Name:</label>
                </td>
                <td>
                    <input type="text" size=15 name="lastName" value="<% if(isReturned){ %> <%= user.lastName %> <% } %>"/>
                </td>
                <% if(errors != null && typeof errors.lastName !== 'undefined' && errors.lastName !== null){ %>
                    <td class="error"><%= errors.lastName.msg %></td>
                <% } %>
            </tr>
            <tr>
                <td>
                    <label for="email">E-mail:</label>
                </td>
                <td>
                    <input type="text" size=15 name="email" value="<% if(isReturned){ %> <%= user.email %> <% } %>"/>
                </td>
                <% if(errors != null && typeof errors.email !== 'undefined' && errors.email !== null){ %>
                    <td class="error"><%= errors.email.msg %></td>
                <% } %>
            </tr>
            <tr>
                <td>
                    <label for="password">Password:</label>
                </td>
                <td>
                    <input type="password" size=15 name="password"/>
                </td>
                <% if(errors != null && typeof errors.password !== 'undefined' && errors.password !== null){ %>
                    <td class="error"><%= errors.password.msg %></td>
                <% } %>
            </tr>
            <tr>
                <td>
                    <label for="confirm">Confirm Password:</label>
                </td>
                <td>
                    <input type="password" size=15 name="confirm"/>
                </td>
                <% if(errors != null && typeof errors.confirm !== 'undefined' && errors.confirm !== null){ %>
                    <td class="error"><%= errors.confirm.msg %></td>
                <% } %>
            </tr>
            <tr>
                <td colspan=2>
                    <input type="submit" size=15 name="submit" value="Register"/>
                </td>
            </tr>
        </table>
    </form>
<% _.template('footer') %>

This is what I tried after the comment I got (I don't specify a specific url, because expressjs wires up a views directory, and specifying just the name of the template works in every other part of the project). It just doesn't resolve the header and footer templates now.

4
  • Since underscore.js templates contain just JavaScript, can't you do something like "<% _.template(...); %> in your template? If that's not possible, I'd suggest simply first regex-replacing your includes with their target, before invoking _.template. Commented Dec 26, 2012 at 17:11
  • Told you it was a basic question. :) I'm new to underscore... Soo... Thank you very much. :) That worked. If you want to submit an answer, I'll vote it up. Commented Dec 26, 2012 at 17:13
  • Wait, that actually didn't work. It got rid of the error, but it doesn't correctly resolve the template. Commented Dec 26, 2012 at 17:16
  • underscore's templating engine is pretty basic. Have you considered using others that already support partials out of the box? Commented Dec 26, 2012 at 17:31

1 Answer 1

4

Although underscore.js' template engine is pretty basic, the fact that the template can execute arbitrary JavaScript code allows you to do pretty much anything.

I set up this little helper function to render a template based on an script block with an id:

_.include = function(id, data) { 
    var template = document.getElementById(id).innerHTML;
    return _.template(template)(data); 
}

And this combination of HTML and templates:

<script type="text/html" id='header'>
    This is the header
</script>

<script type="text/html" id='footer'>
    This is the footer
</script>

<script type="text/html" id='full'>
    <%= _.include('header') %>
        <h1><%= title %></h1>
    <%= _.include('footer') %>
</script>

<div id='target'>
    This text will be replaced by the output of rendering the templates
</div>

​ With these it is as easy as this to render the template, header and footer:

document.getElementById('target').innerHTML = _.include('full', { "title": "Title"});

​ Note that I don't pass anything into the _include calls in the template yet. You can probably either pass on the arguments you got (I just didn't get to looking up the name of the context variable yet) or you can explicitly pass on a new object with whatever the header and footer need:

<%= _.include('header', { 'title': title }) %>

A fiddle that contains the code and HTML can be found here: http://jsfiddle.net/tUzcU/2/

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.