Workaround to dynamic includes in Pug/Jade

前端 未结 3 1576
粉色の甜心
粉色の甜心 2021-01-20 23:59

I understand that Pug does not support dynamic includes or extends in templates. Ie

extend path/to/template 

works but not

ex         


        
相关标签:
3条回答
  • 2021-01-21 00:41

    There is no way to do this for now, but you can work out your application architecture without dynamic extends.

    Possible solution #1

    1. Make a layout.jade that conditionally include multiple layouts:

      layout.jade:
      
      if conditionalVariable
          include firstLayout.jade
      else
          include otherLayout
      
    2. In your view, extend layout.jade, and define conditionalVariable in the controller (true/false):

      view.jade:
      
      extends layout
      
      block content
          p here goes my content!
      

    Possible solution #2

    1. Pass configurations to the layout

      - var lang = req.getLocale();
      doctype html
         block modifyLayout
      
    2. split the project into multiple entrances, each entrance extends the layout and passes its different configs, and includes different things in different blocks

      extends ../layout
      block modifyLayout
         - var lang = "en" //force language to be en in this page.
      block body
         include my-page-body
      

    Possible solution #3

    use something like terraform which uses pug as its rendering engine, but it enables you to use dynamic partials like this

    != partial(dynamicFileFromVariable)
    
    0 讨论(0)
  • 2021-01-21 00:52

    I had this issue aswell and found this question while searching for a solution. My solution is similar to Nikolay Schambergs Answer, but i thought i should share it.

    I've created a function that renders templates by giving it a path and passed it to the options object. Maybe it helps in your case aswell

    const includeFunc = (pathToPug, options = {}) => {
        return pug.renderFile(pathToPug, options); //render the pug file
    }
    
    const html = pug.renderFile('template.pug', {include: includeFunc});
    

    and then use it as followed in your template:

    body
      h1 Hello World
      |!{include(dynamicPugFilePathFromVariable)}
    
    0 讨论(0)
  • 2021-01-21 00:59

    In order to do dynamic include, you will have to use Unescaped String Interpolation, inserting pug contents that are pre-compiled before your main .pug file inside your route. In other words it works as follows:

    1) Some .pug files are pre-compiled into HTML 2) The HTML gets fed into another .pug file compilation process

    Here's an example how to do it

    Inside your router file (routes.js or whatever)

    var pug = require('pug')
    var html = []
    var files = ['file1','file2'] // file names in your views folders
    let dir = path.resolve(path.dirname(require.main.filename) + `/app/server/views/`)
    //dir is the folder with your templates
    app.get('/some-route', (req,res) => {
        for (let n = 0; n < files.length; n++) {
    
            let file = path.resolve(dir + '/' + files[n] + `.pug`)
            fs.access(file, fs.constants.F_OK, (err) => {
                if (!err) {
                    html.push(pug.renderFile(file, data))
                    if (n === files.length - 1) {
                        res.render('dashboard', {html})
                    }
                }
                else {
                    res.status(500).json({code:500,status:"error", error:"system-error"})
                }
            })
        }
    })
    

    Inside your desired .pug file:

    for item in html
        .
            !{item}
    

    The example above is specific to my own use case, but it should be easy enough to adapt it.

    0 讨论(0)
提交回复
热议问题