最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to get access to request object from custom handlebars helper - Stack Overflow

programmeradmin5浏览0评论

I'm using handlebars with node.js and express and I have a custom registered helper for temperature display that I'd like to have access to a query parameter from the page URL.

The concept behind the helper is to handle Fahrenheit to Celsius conversion automatically based on whether ?tempFormat=F or tempFormat=C is in the URL or not. Here's the pseudo code for the custom helper I'd like to have:

hbs.registerHelper("formatTemp", function(temp) {
    if (query parameter says to use Fahrenheit) {
        temp = toFahrenheitStr(temp);
    }
    return temp;
});

So, I'd like my template to look like this:

{{#each temperatures}}
    <div class="row {{{stripes @index}}}"> 
        <div class="time">{{prettifyDate t}}</div>
        <div class="atticTemp">{{formatTemp atticTemp}}</div>
        <div class="outsideTemp">{{formatTemp outsideTemp}}</div>
        <div class="spacer"></div>
    </div>
{{/each}}

I'm working around the issue now by pulling request.query.tempFormat and putting it in the data given to the template rendering:

app.get('/debug', function(request, response) {
    var tempData = {
        temperatures: data.temperatures,
        units: request.query.tempFormat || "C"
    };
    response.render('debug', tempData);
});

And, then passing that data in the template:

{{#each temperatures}}
    <div class="row {{{stripes @index}}}"> 
        <div class="time">{{prettifyDate t}}</div>
        <div class="atticTemp">{{formatTemp atticTemp ../units}}</div>
        <div class="outsideTemp">{{formatTemp outsideTemp ../units}}</div>
        <div class="spacer"></div>
    </div>
{{/each}}

But, this seems messy because I have to pass the temperature units to every template render call and I have to then put them in every template where I want them used by a temperature display. They're sitting there in the request object already. So, I'm trying to figure out how to get access to the request object from a handlebars custom helper function? That way, I could save code for every render and save code in each template and have the tempFormat query parameter just automatically apply to any use of formatTemp in my templates.

Does anyone know how to get access to the request object from a handlebars custom helper without using a global?

I'm using handlebars with node.js and express and I have a custom registered helper for temperature display that I'd like to have access to a query parameter from the page URL.

The concept behind the helper is to handle Fahrenheit to Celsius conversion automatically based on whether ?tempFormat=F or tempFormat=C is in the URL or not. Here's the pseudo code for the custom helper I'd like to have:

hbs.registerHelper("formatTemp", function(temp) {
    if (query parameter says to use Fahrenheit) {
        temp = toFahrenheitStr(temp);
    }
    return temp;
});

So, I'd like my template to look like this:

{{#each temperatures}}
    <div class="row {{{stripes @index}}}"> 
        <div class="time">{{prettifyDate t}}</div>
        <div class="atticTemp">{{formatTemp atticTemp}}</div>
        <div class="outsideTemp">{{formatTemp outsideTemp}}</div>
        <div class="spacer"></div>
    </div>
{{/each}}

I'm working around the issue now by pulling request.query.tempFormat and putting it in the data given to the template rendering:

app.get('/debug', function(request, response) {
    var tempData = {
        temperatures: data.temperatures,
        units: request.query.tempFormat || "C"
    };
    response.render('debug', tempData);
});

And, then passing that data in the template:

{{#each temperatures}}
    <div class="row {{{stripes @index}}}"> 
        <div class="time">{{prettifyDate t}}</div>
        <div class="atticTemp">{{formatTemp atticTemp ../units}}</div>
        <div class="outsideTemp">{{formatTemp outsideTemp ../units}}</div>
        <div class="spacer"></div>
    </div>
{{/each}}

But, this seems messy because I have to pass the temperature units to every template render call and I have to then put them in every template where I want them used by a temperature display. They're sitting there in the request object already. So, I'm trying to figure out how to get access to the request object from a handlebars custom helper function? That way, I could save code for every render and save code in each template and have the tempFormat query parameter just automatically apply to any use of formatTemp in my templates.

Does anyone know how to get access to the request object from a handlebars custom helper without using a global?

Share Improve this question asked Sep 1, 2014 at 18:51 jfriend00jfriend00 708k103 gold badges1k silver badges1k bronze badges 3
  • On a related note, does anyone know if there is a forum where handlebars issues are discussed where it might be more likely to find handlebars experts (since there has been no activity on this question)? – jfriend00 Commented Sep 2, 2014 at 5:03
  • location.pathname.indexOf('tempFormat=F') – raidendev Commented Sep 3, 2014 at 8:23
  • @raidendev - this isn't a browser, it's a server running node.js and it would have been in location.search, not location.pathname if it was a browser and I'm trying to avoid using globals so multiple requests don't have issues. – jfriend00 Commented Sep 3, 2014 at 14:33
Add a ment  | 

3 Answers 3

Reset to default 11

First you need to assign your request object to the response local by registing a middleware anywhere before your route

app.use(function(req,res,next){
    res.local.req = req;
    next();
})

Then you could access the query object in you helper

<div class="atticTemp">{{formatTemp atticTemp ../req.query.tempFormat }}</div>

Handlebars always invokes helpers with the current context as this, so you can invoke the block with this to evaluate the block in the current context.

https://handlebarsjs./block_helpers.html#basic-blocks

You can bine @Roland's answer with this feature to have your helper determine the correct format with a single parameter.

First add a middleware to inject the value from the request into the context for handlebars.

app.use(function(req, res, next){
    var tempUnits = this.req.query.tempFormat || 'C';
    this.locals.tempUnits = tempUnits;
    next();
})

Then in your middleware function, you can use this.tempUnits to access the value you injected.

hbs.registerHelper("formatTemp", function(temp) {
    var units = this.tempUnits;
    if (units == 'F') {
        temp = toFahrenheitStr(temp);
    }
    return temp;
});

Then you can have your single parameter helper that gets data from the request.

<div class="atticTemp">{{formatTemp atticTemp}}</div>

Note: You can add the whole request object, but it's cleaner to have the middleware inject the value you want.

I'm using express-handlebars package. You can register helpers on it's config object as below. Slightly differs from your way but you'll get the idea. To shorten the things, i've just added a second parameter in your helper function (:

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

app.engine('handlebars', exphbs({
    defaultLayout: 'layout',
    helpers : {
        formatTemp: function(temp, unit) {
            console.log(unit);
            if (unit=="F") {
                return temp;
            } else {
                return 32 + (temp* 9 / 5);
            }
        }
    }

context data structure and the usage is the same.

tested.

发布评论

评论列表(0)

  1. 暂无评论