ExpressJS & Swig: Changing template variables based on route?

I’m developing an app using MEAN.js, and I’m trying to fix the Articles (blog) so it’s more friendly for social sharing. The problem I’m having is populating the open graph meta data so that it populates the og:url value with the actual url being shared. Here are what the files look like:

express.js

  • Doing an async call within a dynamicHelper (or some alternative) in Express 2.x
  • How to show last 20 tweets with twitter api on express.js with node.js?
  • Force SSL with expressjs 3
  • NodeJS/Express: Errors using Bliss as the template engine
  • Getting data from/writing data to localhost with Express
  • using partials with express in node.js
  • // Setting application local variables, to be rendered in the template's variables in layout.server.view.html below.
    app.locals.siteName = config.app.siteName;
    app.locals.title = config.app.title;
    app.locals.description = config.app.description;
    app.locals.keywords = config.app.keywords;
    app.locals.imageUrl = config.app.imageUrl;
    app.locals.facebookAppId = config.facebook.clientID;
    app.locals.jsFiles = config.getJavaScriptAssets();
    app.locals.cssFiles = config.getCSSAssets();
    
    // Passing the request url to environment locals
    app.use(function(req, res, next) {
    
        // NOTE: This is the line that's setting the url on the layout template.
        res.locals.url = req.protocol + '://' + req.headers.host + req.url;
        next();
    });
    

    layout.server.view.html

    // This is the template being rendered, using Swig as the template engine.
    // The variables (e.g. siteName, title, etc.) are being set using the app.locals and req.locals.url variables in the express.js file above.
    
    <!-- Facebook META -->
    <meta id="fb-app-id" property="fb:app_id" content="{{facebookAppId}}">
    <meta id="fb-site-name" property="og:site_name" content="{{siteName}}">
    <meta id="fb-title" property="og:title" content="{{title}}">
    <meta id="fb-description" property="og:description" content="{{description}}">
    <meta id="fb-url" property="og:url" content="{{url}}">
    <meta id="fb-image" property="og:image" content="{{imageUrl}}">
    <meta id="fb-type" property="og:type" content="website">
    
    <!-- Twitter META -->
    <meta id="twitter-title" name="twitter:title" content="{{title}}">
    <meta id="twitter-description" name="twitter:description" content="{{description}}">
    <meta id="twitter-url" name="twitter:url" content="{{url}}">
    <meta id="twitter-image" name="twitter:image" content="{{imageUrl}}">
    

    articles.server.controller.js

    // Accessed only when a user visits one of the 'Articles' (blog) pages.
    // When a user visits a url for an Article, this file grabs the article
    // from the database and updates the local variables with article-specific
    // values. This works for everything EXCEPT the url variable.
    
    exports.articleByUrl = function(req, res, next, id) {
        var url = req.params.articleUrl;
        Article.findOne({urlTitle: url}).populate('user', 'displayName').exec(function(err, article) {
            if (err) return next(err);
            if (!article) return next(new Error('Failed to load article ' + id + ' with friendly URL "' + url + '".'));
            req.app.locals.title = article.title;
            req.app.locals.description = article.summary;
    
            // This is the line that I'm HOPING will update the url variable in
            // the template file above, but it's not working. I've also tried
            // using req.app.locals.url, but that didn't work either.
            res.locals.url = req.protocol + '://' + req.get('host') + '/#!' + req.originalUrl;
    
            req.app.locals.imageUrl = article.img;
            req.article = article;
            next();
        });
    };
    

    Currently, all of the values populate correctly EXCEPT the url value – it always shows the root url (i.e. http://localhost:3000 on my dev machine). Any help, or smarter ways to do what I want would be REALLY appreciated. I’ve spent 2 days on this, and my stubbornness is finally giving out.

  • How to send a POST request from node.js Express?
  • Node.js Express post method is not recognised by WebStorm 6
  • How do do a callback after redirect in expressjs
  • Displaying a JSON dataset as a table with Node.js and Express
  • Grunt — Running a Connect and Express server on the same port
  • Keep data for node app when alive
  • One Solution collect form web for “ExpressJS & Swig: Changing template variables based on route?”

    When you use:

    req.app.locals
    

    It changes all the values for the app for everyone (until server restart). The proper way is to use:

    res.app.locals
    

    BUT when you do, it only does it for the initial page request and doesn’t persist when the hash change is applied on the client side.

    The recommended approach would be to create a new server layout file with the URL in question so there is no hash change, then perhaps your navigation for the new server template file can link back to the URLs in you one-page app (with the original server template).

    Best of luck. 😀