ericf / express-handlebars

A Handlebars view engine for Express which doesn't suck.
BSD 3-Clause "New" or "Revised" License
2.31k stars 384 forks source link

Feature: contentFor block helper #15

Closed shellscape closed 11 years ago

shellscape commented 11 years ago

Love the project. By far the easiest to get going so far for this node.js/express newbie.

The express-hbs project has a really neat feature I'd love to see added. I'm not well enough versed yet to create this and file a pull request. The contentFor helper is basically equiv to content placeholders in asp.net and very useful. Basically allows to adding content to a parent template/layout. Here's the usage from express-hbs

layout.handlebars

{{{block "pageScripts"}}}

index.handlebars

{{#contentFor "pageScripts"}}
  CONTENT HERE
{{/contentFor}}

Is this something we can get added, or would it be possible to get a helper function we can add as middleware?

ericf commented 11 years ago

Thanks! Glad this project is useful to you :)

This feature is definitely something that's perfect for helpers. Here's one way you could go about doing this:

var express = require('express'),
    exphbs  = require('express3-handlebars'),

    app = express(),
    hbs;

hbs = exphbs.create({
    helpers: {
        block: function (name) {
            var blocks  = this._blocks,
                content = blocks && blocks[name];

            return content ? content.join('\n') : null;
        },

        contentFor: function (name, options) {
            var blocks = this._blocks || (this._blocks = {}),
                block  = blocks[name] || (blocks[name] = []);

            block.push(options.fn(this));
        }
    }
});

app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');

// ...

Let me know if this helps (or even works, I didn't test it.)

shellscape commented 11 years ago

That's awesome. I'll play with this some tomorrow. Thanks!

ericf commented 11 years ago

@shellscape Did this end up working out for you?

shellscape commented 11 years ago

Haven't yet gotten to test that, but its in the pipe. Thanks very much. On Mar 27, 2013 1:57 PM, "Eric Ferraiuolo" notifications@github.com wrote:

@shellscape https://github.com/shellscape Did this end up working out for you?

— Reply to this email directly or view it on GitHubhttps://github.com/ericf/express3-handlebars/issues/15#issuecomment-15540748 .

ericf commented 11 years ago

Closing this…

smencer commented 10 years ago

Just thought I'd chime in to say I was able to get the sample code above working in my application with a small modification:

    helpers: {
      block: function(name){
        var blocks = this._blocks;
            content = blocks && blocks[name];
        return content ? content.join('\n') : null;
      },
      contentFor: function(name, options){
        var blocks = this._blocks || (this._blocks = {});
            block = blocks[name] || (blocks[name] = []); //Changed this to [] instead of {}
        block.push(options.fn(this));
      }
    }

I'm now able to define a {{{block "pageScripts"}}} in my layout page and fill it with content from my views inside of:

{{#contentFor "pageScripts"}}
<script>
 // my page specific code here
</script>
{{/contentFor}}

Thanks for the sample code to get me jump started!

MacgyverMartins commented 8 years ago

It doesn't work for me. It just returns a string inside the HTML and nothing happens

contact.hbs

{{#contentFor "pageScripts"}}
  <script src="js/pace.min.js"></script>
  <script src="js/wow.min.js"></script>
{{/contentFor}}

main.hbs

{{block "pageScripts"}}
panlw commented 8 years ago

Great!

ignacionr commented 8 years ago

This is working really well. Cheers!!

rajitha-bandara commented 6 years ago

To properly run js, instead of displaying it, I needed to change the notation from {{block "pageScripts"}} to {{{block "pageScripts"}}}