Finding current url inside EJS view when using express

后端 未结 3 1464
鱼传尺愫
鱼传尺愫 2020-12-11 17:51

I\'m using Express and EJS to serve pages. I\'m using Bootstrap for the UI, specifically the navbar.

I\'d like to add an \'active\' class to the current

相关标签:
3条回答
  • 2020-12-11 18:31

    In pretty much every node/express templating language I've used (ejs, kiwi, swig, jade), the answer is no. I've always just set a variable called "active" and then checked for it. As you say, it's not a great answer, though I don't know that scalability is the issue. If every url renders it's own view (or even if you have a common handler for view rendering), it shouldn't be that hard to say something like req.active = "Somepage". Another possibility would be to add middleware that does it for you based on the route. Something like

    app.use(function(req, res, next){
        req.active = req.path.split('/')[1] // [0] will be empty since routes start with '/'
        next();
    });
    

    Then you just make sure any routes that have a corresponding nav component use unique paths, like

    app.get('/students', ....)
    app.get('/classes', ....)
    app.get('/teachers', ....)
    // etc.
    

    EDIT: In response to your comment, I always throw ALL my view stuff into one object key inside req, and usually I name the key by whatever templater I'm using. So I would probably actually use the above example to set req.ejs.active and then do

    res.render('myview', req.ejs);
    

    This method makes it much easier to separate logic out into multiple middleware functions and not have to pass a huge anonymous object to res.render.

    0 讨论(0)
  • 2020-12-11 18:34

    As far as I know, you can't do what you're asking for unless you modify EJS internally. However, a less bothersome solution would be to pass the URL property of the request on each page invocation, rather than define it per route.

    app.get('/url', function (req, res) {
      res.render('view', {
        page: req.url,
        nav: {
          'Page 1': '/page1',
          'Page 2': '/page2',
          'Page 3': '/page3'
        }
      });
    });
    

    If you only wanted to get the first part of the URL and match it, then you could just call split('/') on req.url. You could then put a loop inside your template file to create the list for your navigation bar.

    <% nav.forEach(function(title) { %>
      <% if (nav[title] == page) { %>
        <li class="active">This part of the navigation bar is active.</li>
      <% } else { %>
        <li>This part of the navigation bar is normal.</li>
      <% } %>
    <% }) %>
    
    0 讨论(0)
  • 2020-12-11 18:48

    index.js

    /* object menu */
    const menu = [
        {
            name: 'Home',
            url: '/'
        },
        {
            name: 'About',
            url: '/about'
        }
    ]
    
    /* route */
    app.get( '/', function( request, response) {
    
        let data = {
            title: 'Home',
            url: request.url,
            menu: menu
        }
    
        response.render( 'home', data )
    
    } )
    
    app.get( '/about', function( request, response) {
    
        let data = {
            title: 'About',
            url: request.url,
            menu: menu
        }
    
        response.render( 'about', data )
    
    } )
    

    menu.js

        <% for ( let i in menu ) { %> // loop menu
            <% if ( menu[i].url == url ) { %> // match, add active in class
    
                <a class="active" href="<%= menu[i].url %>" ><%= menu[i].name %></a>
    
            <% } else { %>
    
                <a class="" href="<%= menu[i].url %>" ><%= menu[i].name %></a>
    
            <% } %>
        <% } %>
    
    0 讨论(0)
提交回复
热议问题