Sharing HTML Templates between nodes

709 views
Skip to first unread message

Julian Knight

unread,
Mar 29, 2015, 8:43:07 AM3/29/15
to node...@googlegroups.com
Hi all,

In my home automation system, I want to have all output web pages share the same template so that, in each template node, I'm only coding the specifics for that page. Everything else should be in the master template. For example common scripts, menu, CSS, etc.

What is the best way to do this?

I've tried to use Mustaches include feature {{> templatename}} with the template file templatename.mustache but I can't get this to work and the instructions for the mustache implementation included in NR seem to indicate that you have to do this through a separate script (jQuery?).

This all seems overly complex to me. Isn't there a better way to achieve this without significant amounts of coding?

Dave C-J

unread,
Mar 29, 2015, 10:53:07 AM3/29/15
to node...@googlegroups.com
If they are static resources then just share them from a static directory
see the httpStatic parameter in settings.js

Julian Knight

unread,
Mar 29, 2015, 11:51:37 AM3/29/15
to node...@googlegroups.com
That didn't work I'm afraid. I created a file called "incBottom.mustache" in the static folder and added "{{> incBottom}}" in the template but it didn't include it.

Nicholas O'Leary

unread,
Mar 29, 2015, 12:17:35 PM3/29/15
to node...@googlegroups.com

That isn't what Dave meant. If your pages reference any static assets, such as images, stylesheets, js files etc, you can use httpStatic to serve those files without having to create flows for them.

To your actual question, we don't support partials in our template node, but you can easily achieve a similar effect by using multiple template nodes in series.

Create a template node that renders your complete page with placeholders in the places you want custom content. Then create a template node for each page that creates the custom content for that page. Then have a separate flow to each of the page templates, which all flow into the one complete page template and out to an Http response node.

Nick




--
http://nodered.org
---
You received this message because you are subscribed to the Google Groups "Node-RED" group.
To unsubscribe from this group and stop receiving emails from it, send an email to node-red+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Nicholas O'Leary

unread,
Mar 29, 2015, 3:03:16 PM3/29/15
to Node-RED Mailing LIst
In case my description wasn't clear, something a bit like this:

Inline images 1

Nick

Dave C-J

unread,
Mar 29, 2015, 3:07:16 PM3/29/15
to node...@googlegroups.com
Yeah - sorry - when I saw Julian mention CSS and common scripts, I tend to put them in separate files so I assumed static - but yeah - like the tiered approach.

Julian Knight

unread,
Apr 1, 2015, 3:11:16 PM4/1/15
to node...@googlegroups.com
Thanks guys, that does go some way towards an answer.

However, the idea of partials is that they can be reused anywhere. This is particularly useful with something like NR where flows in different parts of the UI (different tabs for example, because they belong to different types of processes such as showing the latest weather or a graph of temperature/Humidity for part of the house) need the same wrapping HTML including the static resources such as CSS, jQuery, websockets connections and so on.

Probably the easiest way to achieve this is to have the option of loading the template node from a file instead of just from the UI - much like the contributed function node. Then your design pattern Nick would work OK, though even then it would be tricky for newcomers to understand, especially because you would often have bits of templated output in different parts of the standard template. for example, you would want the page title to be dynamic then a bunch of standard template common to all output, then the main dynamic output for the page and then some standard output again. You might even need a second set of dynamic/standard output - typically some script output in a specific order of execution such as a script specific to the current page followed by some standard script.

<html>
 
<head>
   
<title>{{pageTitle}}</title>
    ... standard stuff like UI settings, CSS, JS files ...
    --- maybe some dynamic metadata here ---
 
</head>
 
<body>
    ... standard page output such as a menu and the main page structure ...
    --- main dynamic output here ---
    ... more standard output such as page footers, sidebars, etc.  also late loading javascript files ...
    --- maybe some more javascript specific to this page ---
    ... more standard javascript loading ...
 
</body>
</html>


See what I mean? I don't think there is any clean and easily understood way of doing this yet in NR?

Nicholas O'Leary

unread,
Apr 1, 2015, 3:24:44 PM4/1/15
to Node-RED Mailing LIst
If you put the template in a subflow, you can add as many instances as you want, wherever you want.

Storing templates/functions in external files isn't a pattern we encourage as it reduces the portability of a flow. (You can't just export the flow, you have to copy all the files, make sure they are in the right location, or update the file references in the flow.... and on cloud platforms, you don't have that sort of file-system access.)

What you describe isn't a unique problem for node-red, its more a question of how you choose to structure your templates - regardless of whether running in NR or not.

Here's your example HTML, but I've replaced the dynamic bits with mustache inserts:

<html>
  
<head>
    
<title>{{pageTitle}}</title>

    ... standard stuff like UI settings, CSS, JS files ...
    {{metaData}}
  
</head>

  
<body>
    ... standard page output such as a menu and the main page structure ...
    {{dynamicContent}}

    ... more standard output such as page footers, sidebars, etc.  also late loading javascript files ...
    {{pageSpecificJS}}

    ... more standard javascript loading ...
  
</body>
</html>

You just pass this a message with msg.pageTitle, msg.metaData, msg.dynamicContent and msg.pageSpecificJS all set to appropriate values.
How your flow sets these properties on the message is up to you - it may be through template nodes, it maybe via the Change node to set simple strings (probably sufficient for pageTitle, for eg) or a Function node.




Nick





--
http://nodered.org
---
You received this message because you are subscribed to the Google Groups "Node-RED" group.
To unsubscribe from this group and stop receiving emails from it, send an email to node-red+u...@googlegroups.com.

Julian Knight

unread,
Apr 1, 2015, 4:10:41 PM4/1/15
to node...@googlegroups.com
Drat! Forgot subflows. OK, I think I'm getting there. I've created a subflow just containing the master template.

For each instance of the subflow, I need to pass in three lots of Mustache formatted content (the metadata, the main body of the page, a setup script block that changes for each page).

But, the output from each template node is always on msg.payload. So I have to:
  1. Feed into the template an existing message where I've moved the payload to somewhere else
  2. Feed the output of the template node into a change node to move the msg.payload again to somewhere else
  3. Do that a second time
  4. Do that a third time
  5. Finally, feed the whole lot into the subflow.
That seems pretty heavy just to get what I need. What was a couple of nodes for each page output is now 7 nodes and a subflow. Is there a simpler way that I'm missing? It would be easier if there was a control to change the output element on the template to something other than msg.payload.

Thanks for your continuing help.

Nicholas O'Leary

unread,
Apr 1, 2015, 4:13:41 PM4/1/15
to Node-RED Mailing LIst
Julian... there is an option on the template node for what property to set.


Nick

Dave C-J

unread,
Apr 1, 2015, 4:28:37 PM4/1/15
to node...@googlegroups.com
Inline images 1

Julian Knight

unread,
Apr 1, 2015, 4:40:32 PM4/1/15
to node...@googlegroups.com
OK, I give up, I'm an idiot!! I was thinking that was for the input not the output - I'll just go and stand in a corner for a while!

Thanks.

On Wednesday, 1 April 2015 21:28:37 UTC+1, Dave C-J wrote:
Inline images 1

Julian Knight

unread,
Apr 1, 2015, 4:55:22 PM4/1/15
to node...@googlegroups.com
Yes, it Works!! One step close to world domination (said stroking the cat manically!)

Now I can really move forwards with a full home UI with a standard look and feel.

Glenn McCallum

unread,
Nov 16, 2017, 5:03:20 PM11/16/17
to Node-RED
Any Example flows to show us your work as looking for similar solution

Cheers

Julian Knight

unread,
Nov 16, 2017, 5:31:42 PM11/16/17
to Node-RED
What are you looking to do?
Reply all
Reply to author
Forward
0 new messages