Search code examples
node.jshandlebars.jsexpress-handlebars

Inserting both Script tags and Body tags into NodeJS Handlebars template


My question is whether or not it is possible to inject both body and script tags into a handlebars template. I have looked over the web but have only found confusing tutorials/example. To give an example, I have the following already setup and it works fine:

layout.hbs:

<!DOCTYPE html>
<html>
    <head>  
    </head>
    <body>
        {{{ body }}}
    </body>
</html>

index.hbs:

<h1>test</h1>

server.js:

const express = require('express');
const hbs  = require('express-handlebars');
app.engine('hbs',hbs({extname: 'hbs'}))
app.set('view engine', 'hbs');

BUT! What I want to also achieve is something where I can also add scripts from my index.hbs into my layout.hbs in the following fashion:

layout.hbs:

<!DOCTYPE html>
<html>
    <head>
        {{{ script }}}  
    </head>
    <body>
        {{{ body }}}
    </body>
</html>

index.hbs:

<script>
    <script src="example.js" defer></script>
</script>
<body>
    <h1>test</h1>
</body>

Is this possible? and if so, what changes will I have to make


Solution

  • Depending on what exactly you are trying to accomplish, I would suggest putting the script in the layout.

    As an example:

    layout.hbs:

     <!DOCTYPE html>
    <html>
     <body>
     {{> nav }}
     {{{body}}}
     {{> footer }}
    <script src="/js/file-validation.js"></script>
    </body>
    </html>
    

    file-validation.js

    (function() {
    'use strict';
    window.addEventListener('load', function() {
        // Fetch all the forms we want to apply custom Bootstrap validation styles to
        var forms = document.getElementsByClassName('needs-validation');
        // Loop over them and prevent submission
        var validation = Array.prototype.filter.call(forms, function(form) {
            form.addEventListener('submit', function(event) {
                if (form.checkValidity() === false) {
                    event.preventDefault();
                    event.stopPropagation();
                }
                form.classList.add('was-validated');
            }, false);
        });
    }, false);
    

    })();

    support.hbs

     <form action="{{feedbackEmail}}"
                      method="POST" class="needs-validation" novalidate>
               <div class="form-row">
                        <div class="form-group col-md-6">
                            <label for="inputName">Name</label>
                            <input  name=name type="text" class="form-control" id="validationName" placeholder="Name" aria-describedby="inputGroupPrepend" required>
                            <div class="invalid-feedback">
                                Please enter your name.
                            </div>
                        </div>
                        <div class="form-group col-md-6">
                            <label for="inputEmail4">Email</label>
                            <input name="email" type="email" class="form-control" id="validationEmail" placeholder="You@email.com" aria-describedby="inputGroupPrepend" required>
                            <div class="invalid-feedback">
                                Please enter your email.
                            </div>
                        </div>
                    </div>
                  <button type="submit" class="btn btn-primary">Submit</button>
                </form>
    

    This way when you put together your partials it will call the script on any .hbs file you implemented it on.

    In this example it is done by the needs-validation class on a support form.