How to get access to request object from custom handlebars helper

不想你离开。 提交于 2020-01-14 09:35:08

问题


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?


回答1:


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>



回答2:


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.




回答3:


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.com/block_helpers.html#basic-blocks

You can combine @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.



来源:https://stackoverflow.com/questions/25611501/how-to-get-access-to-request-object-from-custom-handlebars-helper

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!