I set up a node.couchapp.js CouchApp and pushed it to my CouchDB. There is Sammy and jQuery included by default. Now, I'd like to add Mustache for templates, but don't exactly know where? I could use it as Node.js module or jQuery plugin.
I started with some sample code, just to see if it works, but it doesn't:
ddoc.lists = {
"basic": "function (head, req) { var that = this; provides('html', function () { var to_html = require('modules/mustache').to_html; var members = []; var row; while (row = getRow()) { members.push({club: row.key[0], name: row.key[1]}); } return to_html(that.templates['roster.mustache'], { members: members }); }) }"
};
Results in:
{"error":"invalid_require_path","reason":"Object has no property \"modules\". ...
Project structure is:
. Project
| - app.js
| - attachments
| - - scripts
| ` - index.html
| - modules
| | mustache
| - ` - mustache.js
` - templates
Update
I modified the code a bit and excluded the template folder as possible cause. This snippet is from a solved question here on SO, so it should actually work. But it's still the same error. I installed mustache.js with npm install mustache and renamed the folder from node_modules to modules (didn't work with node_modules either).
"basic": "function (head, req) { provides('html', function () { var template = '{{%IMPLICIT-ITERATOR}}{{name}}: <ul> {{#items}}<li>{{.}}</li>{{/items}} </ul>'; var mustache = require('./modules/mustache/mustache.js'); return mustache.to_html(template,view);});}"
But it's still the same error.
I'm not sure about the specific error you're getting, but to your question:
"Now, I'd like to add Mustache for templates, but don't exactly know where? I could use it as Node.js module or jQuery plugin."
You can use it in both.
As Node.js runs on the server-side this effectively gives you a way to define your template once (using Mustache in this case) and run it both server-side (using Node.js) and client-side (using the jquery-plugin).
Just for the overview (you may well already know this):
Imagine rendering a search-result of products:
The traditional way is to render the products with some server-side templating engine.
Now, let's say you want to enable filtering / sorting of the search-results. Generally speaking you have 3 options:
do a normal (non-ajax call) to the server, do server-side templating and spit out the new page
do an ajax-call to the server, do server-side templating and spit out html, pick it up client-side and insert it into a dom-element.
do an ajax-call to the server, generate a json-object, which you render client-side using a client-side templating engine (such as Mustache) into a dom-element.
Option 3 is arguably the best solution from a usability standpoint. (quick, low-bandwidth, no page flickering or page jumping, etc. ) . However think about a fallback/non-js way for SEO if you need it.
When implementing option 3 however you now have the situation of needing a server-side templating language to render products on the initial page load, and a client-side templating language to render products returned from subsequent ajax-calls. Both result in the exact same html. Not very DRY.
Here node.js comes into play, which eliminates the need for writing a seperate server-side template. Instead, just let node.js spit out the initial page using the exact same mustache template you use on the client-side.
Of course you could go the only client-side route: spitting out json on the intial page load as well, and render that on the client. This of course if terrible from a seo-standpoint. Some apps don't the search engine indexing however, in which case the 'everything on the client' approach is a good alternative.
Some related questions:
Client-side templating language with java compiler as well (DRY templating)
Good DRY approach to rendering and AJAX updating of page
Related
I am working on an isomorphic javascript app with express + react. We started out using jade for server side templates for static content, but combining the two is quickly becoming unwieldy. We have ended up with something like this:
In the express routes:
router.get("/", function(req, res) {
var webpackStats = require('../../config/webpack-stats.json');
var reactHtml = React.renderToString(HiwApp({}));
var slideshowHtml = React.renderToString(slideshowApp({}));
var config = {
webpackStats: webpackStats,
reactOutput: reactHtml,
slideshowHtml: slideshowHtml
};
res.render("how_it_works/howitworks", config);
});
In Jade:
body
.company-logo.center
#react-main-mount
!= reactOutput
include ./content_block_1.jade
include ./content_block_2.jade
#slideshow-main-mount
!= slideshowHtml
This is very brittle-if we want jsx then a jade template then more jsx, we have to make sure we get the order right.
My idea is to do it all with jsx. I know there is React.renderToStaticMarkup for this sort of thing, but that doesn't solve the problem of mixing dynamic with static pages.
The big questions: if we decide to do all of this with jsx (say layout.jsx which contains all components), then call React.renderToString(App({});, will this be a major performance hit? If so, is there a better way to do it to easily combine static and dynamic blocks?
Although this may be a tiny bit off topic: We stuck with jade templates.
Basically we wanted the flexibility to use a non-react + flux architecture for areas of the site when and if that need arose. Our site is basically made up of a number of smaller SP apps: Site, UserAccount, Team and Admin.
Why did we do this?
Smaller filesize and overhead for users who are not accessing all sections of the site.
Option to "opt out" of React and flux if and when the need arises.
Simpler, server side authentication.
The way we have done it successfully was to render a JSX shell template (Html.jsx) on the server using React.renderToStaticMarkup() and then send it as the response to every server-side express route request that is meant to deliver some HTML to the browser. Html.jsx is just a shell containing html head information and GA scripts etc. It should contain no layout.
// Html.jsx
render(){
return (
<html>
<head>
// etc.
</head>
<body>
<div
id="app"
dangerouslySetInnerHTML={{__html: this.props.markup}}>
</div>
</body>
<script dangerouslySetInnerHTML={{__html: this.props.state}</script>
<script>
// GA Scripts etc.
</script>
</html>
)
}
Remember it is totally fine and even recommended to use dangerouslySetInnerHTML on the server when hydrating your app.
Dynamic layout should be done with your your isomorphic components through a hierarchy of components based on their state/props configuration. If you happen to be using React Router, then your router will render view handlers based on the routes you provide it so that means you don't need to manage that yourself.
The reason we use this technique is to architecturally separate our "App" which is isomorphic and responds to state from our server-side template shell which is just a delivery mechanism and is effectively boiler plate. We even keep the Html.jsx template amongst all the express components within our app and do not let it mix with the other isomorphic React components.
One of the most helpful resources I found for working out React/isomorphic architecture was https://github.com/yahoo/flux-examples/tree/master/react-router which is where we stole this technique from.
We explored the idea of integrating handlebars as a templating engine for client's devs using our products in the future but decided that it was less complex to write our own DSL in JSX and use some simple parsing routines to parse our HTML-like DSL to JSX by adding things like export default (ES6 module syntax) at the start of the template and then import the template to a rendering component.
You could of course follow that line of thought and use a jade compiler to spit out the template and then add module syntax around that if you think separate jade files are essential. I also noticed this project as well although I have not explored it in anger: https://github.com/jadejs/react-jade.
Trying out backbone+express with Jade as default templating.
Following a tutorial here(Great tutorial)
Confusion:
Many tutorials about backbone uses underscore template or handlebar to compile and render view.
I was using Jade as default template engine. My question is if I am using Jade then do I have to use another templating like Handlebar or underscore. If not how can I achieve following in Jade
render: function() {
var template = $("#booktemplate").html();
var compiled = Handlebars.compile(template);
var html = compiled(this.model.attributes);
this.$el.html(html);
return this;
},
My assumption: I am thinking Jade and Handle bar both are templating system and can be used alternatively. Is it so?
Why not use both Jade & Handlebar? I dont want to use two different syntaxes
#{} from jade / {{}} from Handlebar
Using Jade on the browser is not really a simple task. Thing is Jade is built for server side and does not support browsers.
This is why you'll often see people using two templates engines (if they use Jade). Some others are just gonna use Handlebars or Underscore everywhere - this is easier because templates engine working in the browser should work on the server. The other way around is not always true though.
Point to be taken here is that before starting to use a template engine, make sure it supports the environment you wish to target. There's plenty of options in term of engine, and this site can help you find one fittings your need: http://garann.github.io/template-chooser/
If you're really like Jade, then, you can use a stack like Browserify and some middleware (Jadeify) to make it work after pre-compilation. But you need to buy into the browserify concept and accept to precompile everything, everytime. You can check this related question for more details: https://stackoverflow.com/a/6623561/1024223
I have a rather robust project that has all of its templates implemented in Slim and a little Haml. I'm considering moving the project over to a Node.js based structure (probably built atop Tower.js or something similar; maybe Meteor), however I would like to continue using Slim or Haml for the templates rather than shifting over to another template engine.
Has anyone done this or spent the time to figure out how to accomplish this so far, and if so, what were your findings?
Tower.js wraps the express.js template engine system, so you should be able to use any express.js template engine by adding the following to the configuration Tower.View.engine = "haml"
Tower.js uses mint, which has HAML built in, so you just need the haml module in your directory.
Slim is problematic though. First its not within mint.js directly, so you'll need to register a new template engine. Todo that you'll need to
create a function customAdapter that mint.js can use, you can look at the mint.js sourcecode. Heres an example of the haml adapter function:
function(content, options, callback) {
var result;
result = require('hamljs').render(content, options || {});
if (callback) {
callback.call(this, null, result);
}
return result;
}
you'll need to add the adapter to mint.js by doing require("mint").engines.slim = customAdapter
But there's no express.js engine for Slim, and since Slim contains ruby code snippets, it isn't likely there will be.
If you really want to do it so you'll need to create your own javascript parser for the template files (probably using something like http://opalrb.org/ , though with no specific ruby libraries), and then create an express.js engine (which I don't know how to).
I doubt it will be a very fruitful exercise.
I suggest you either convert your Slim files to haml (or jade, or any template engine that can be used by express.js) or don't make the move.
I could also not find any way to automatically convert Slim to haml or any other template engine (probably due to the fact that it contains ruby code), so you will have to do the conversion entirely manually.
I was trying to convince a fellow co-worker into using Mustache/Hogan in the front-end of a project and I proposed the following:
Having a templates.js file, which could roughly look like this:
var tpl_alert = '<div class="alert">{{msg}}</div>';
var tpl_welcome = '<p class="user-{{type}}">Welcome, {{name}}</p>';
...
Then, we would include templates.js and use the corresponding tpl in the Mustache/Hogan.js rendering.
My proposal was turned down, since we're hardcoding html templates into js variables.
Is this really that bad? Which are other alternatives to this?
To answer your question, putting your templates in javascript variables inside a static JavaScript file makes it difficult to maintain your templates. You need to worry about string escaping whenever you want to make a simple change. And 1 syntax error will crash your app.
However, putting all your templates in a single JavaScript file is the fastest way to load your templates.
Your alternatives are:
Storing your templates in seperate files and generating the static template.js file as a prebuild step.
Loading your html template files async through AJAX into javascript variables.
Using a library like Require.js that will load your templates asynchronously as needed into variables.
My preferred way of doing this is to create a separate template file that can be loaded dynamically in development and baked into pure js for production.
Specifically I use eco templates (I wouldn't recommend them unless you're familiar with coffee script) and Stitch for node.js. Stitch supports custom engines tied to file extensions, so when it finds an eco file in my project directory it compiles it into a Javascript function. I can now include that function in any other part of my application using the stitch provided require function using the original path of the eco file. So if the template resided in src/views/listItem.eco I would run var listItemView = require('views/listItem'); to fetch it and use it like this
var html = listItemView({item: items[i]});
$someElement.html(html);
You could use require.js instead of stitch if course, or any other similar framework.
First, 2 common (basic) approaches:
# returning from some FoosController method
respond_to do |format|
# 1. render the out a json representation
format.json { render :json => #foo }
# 2. render an RJS template, say update.js.erb
format.js { render }
end
# in update.js.erb
$('#foo').html("<%= escape_javascript(render(#foo)) %>")
These are obviously simple cases but I wanted to illustrate what I'm talking about. I believe that these are also the cases expected by the default responder in rails 3 (either the action-named default template or calling to_#{format} on the resource.)
The Issues
With 1, you have total flexibility on the view side with no worries about the template, but you have to manipulate the DOM directly via javascript. You lose access to helpers, partials, etc.
With 2, you have partials and helpers at your disposal, but you're tied to the one template (by default at least). All your views that make JS calls to FoosController use the same template, which isn't exactly flexible.
Three Other Approaches (none really satisfactory)
1.) Escape partials/helpers I need into javascript beforehand, then inserting them into the page after, using string replacement to tailor them to the results returned (subbing in name, id, etc).
2.) Put view logic in the templates. For example, looking for a particular DOM element and doing one thing if it exists, another if it does not.
3.) Put logic in the controller to render different templates. For example, in a polymorphic belongs to where update might be called for either comments/foo or posts/foo, rendering commnts/foos/update.js.erb versus posts/foos/update.js.erb.
I've used all of these (and probably others I'm not thinking of). Often in the same app, which leads to confusing code. Are there best practices for this sort of thing? It seems like a common enough use-case that you'd want to call controllers via Ajax actions from different views and expect different things to happen (without having to do tedious things like escaping and string-replacing partials and helpers client side).
Any thoughts?
The best practice is to have your Web UI use the RESTful API. That is, get and put resources in JSON format using JavaScript running in the client, just as a third party might get and put resources in JSON format using RestClient. That means you don't have .rjs or .js.erb templates on the server - you might instead have Mustache or Handlebars or jQuery templates, plus the glue JavaScript, embedded in (or statically linked to from) the HTML page originally delivered to the Web client.
Of course, the quick-and-dirty approach of using remote => true, and going to the server and rendering a JavaScript code template to produce JavaScript that will be executed on the client ... is easier. And it was fairly good practice for a while. But we need JavaScript for a data format now, and we have superior capabilities today for pulling data in JSON format and rendering templates within the client.
Not sure if this work for you, but I would do the following:
Generate .js templates using ERB, these templates will be static
The templates could be mustache, jaml, jQuery Templates or something else.
Use a rake task to generate all templates and create static .js files out of them.
Include these static files using , they will be cached by the browser.
Populate the templates with json data and include the generated html.
This assumes that the templates can in fact be static, which depends on the situation at hand. But generally this should work.