How can I ensure javascript is at the bottom of the code in the express-handlebars template?

I asked the same question for the jade pattern. But now I would like to use the rudders. The main reason is html which is easier for me.

Here is my folder structure:

views 
   |--- home.handlebars
   |--- layouts
          |---- main.handlebars

      

My layout:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>{{title}}</title>
    <link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
    {{{body}}}

    <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>

</body>
</html>

      

The jquery script is loaded at the end after my {{body}} .

Here's my home page template:

<p>This is my home page</p>

<script type="application/javascript">
    $(function() {
        alert( "ready!" );
    });
</script>

      

As you can see, I am trying to load the script at the very end. But unfortunately this is before the jquery script, so my script never gets called. My question is, is there a way as I did in this question for a jade template (to load my own script finally)? Thanks to

+3


source to share


3 answers


I find a solution finally using sections. Here is my app.js:

var exphbs = require('express-handlebars');

var app = express(),
    hbs = exphbs.create({

        defaultLayout:'main',
        helpers: {
            section: function(name, options){ 
                if(!this._sections) this._sections = {};
                this._sections[name] = options.fn(this); 
                return null;
            } 
        }    
    });

app.set('views', path.join(__dirname, 'views'));
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');

      

My layout file main.handlebars :

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>{{title}}</title>
    <link rel="stylesheet" href="/stylesheets/style.css">
    {{{_sections.style}}}
</head>
<body>
    {{{body}}}

    <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
    {{{_sections.script}}}
</body>
</html>

      



My home.handlebars template file :

<p>This is my home page</p>

{{#section 'script'}}

<script type="application/javascript">
    $(function() {
        alert( "I'm ready!" );
    });
</script>

{{/section}}

      

Everything is the same as in my jade template. The only additional work is that I have to use the helpers function in the app.js file.

+6


source


Since handlebars does not support blocks that can be overridden and used at different times, I would take the asset manager approach.

You can put a list of scripts to be included in a specific array in your application. Then in your layout, you can skip them all at the very bottom. The only caveat is that you must specify it inside your application logic, which some people find to be messy.

applications:

app.use(function (req, res, next) {
  res.locals.scripts = [];
  res.locals.scripts.push('/assets/js/common.js');
});

// ...

app.get('/your/route', function (req, res) {
  res.locals.scripts.push('/assets/css/something_specific.js');
  res.render('mykoolpage.hb', { some: 'variables here'  });
});

      



template:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>{{title}}</title>
    <link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
    {{{body}}}

    <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
    {{#each scripts}}<script src="{{this}}"></script>
{{/each}}
</body>
</html>

      

Since you said you were pretty new to the expression, I just wanted to make one clarification: you don't need to pass res.locals

to the template in res.render()

, it is automatically added. app.locals

works the same way.

0


source


I can change the layout of main like this:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>{{title}}</title>
    <link rel="stylesheet" href="/stylesheets/style.css">
    {{style}}
</head>
<body>
    {{> page/title}}
    {{> page/nav}}
    {{{body}}}

    <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
    {{{script}}}
</body>
</html>

      

And then in my router:

var express = require('express');
var router = express.Router();

var script = '<script type="application/javascript">' +
    '$(function() {' +
        'alert( "ready!" );' +
    '});' +
'</script>';

router.get('/', function(req, res) {
  res.render('home', { title: 'My title',
                     script:script});
});

module.exports = router;

      

It works. But this is not elegant and inconvenient because I cannot do it through customizing the template file itself. Are there any better methods?

-1


source







All Articles