{"action":"created","issue":{"url":"https://api.github.com/repos/dadi/web/issues/50","repository_url":"https://api.github.com/repos/dadi/web","labels_url":"https://api.github.com/repos/dadi/web/issues/50/labels{/name}","comments_url":"https://api.github.com/repos/dadi/web/issues/50/comments","events_url":"https://api.github.com/repos/dadi/web/issues/50/events","html_url":"https://github.com/dadi/web/pull/50","id":146910409,"number":50,"title":"Add support for client-side template rendering","user":{"login":"eduardoboucas","id":4162329,"avatar_url":"https://avatars.githubusercontent.com/u/4162329?v=3","gravatar_id":"","url":"https://api.github.com/users/eduardoboucas","html_url":"https://github.com/eduardoboucas","followers_url":"https://api.github.com/users/eduardoboucas/followers","following_url":"https://api.github.com/users/eduardoboucas/following{/other_user}","gists_url":"https://api.github.com/users/eduardoboucas/gists{/gist_id}","starred_url":"https://api.github.com/users/eduardoboucas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eduardoboucas/subscriptions","organizations_url":"https://api.github.com/users/eduardoboucas/orgs","repos_url":"https://api.github.com/users/eduardoboucas/repos","events_url":"https://api.github.com/users/eduardoboucas/events{/privacy}","received_events_url":"https://api.github.com/users/eduardoboucas/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dadi/web/labels/Feature%20request","name":"Feature request","color":"207de5"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":14,"created_at":"2016-04-08T12:05:22Z","updated_at":"2016-04-11T12:10:17Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/dadi/web/pulls/50","html_url":"https://github.com/dadi/web/pull/50","diff_url":"https://github.com/dadi/web/pull/50.diff","patch_url":"https://github.com/dadi/web/pull/50.patch"},"body":"# Overview\r\n\r\nThis PR introduces the ability for Dust templates (both pages and partials), to be rendered on the client, as well as on the server. This feature came about as a requirement for Publish, but I think it would be a great addition to Web.\r\n\r\nTransforming a Dust template into HTML happens in two phases: compiling, where a template is converted into a JavaScript function, and rendering, where that function returns a string of HTML based on the arguments it received. Both phases can happen on the server and on the client (see [*Compiling and Rendering*](http://www.dustjs.com/guides/rendering/)).\r\n\r\nWhen rendering on the client, it's preferable to compile on the server, as that removes a good part of the heavy-lifting from the client and the Dust client-side library required is lighter (`dust-core` instead of `dust-full`). With Web, we're already compiling all the templates on the server anyway, so we just need to make them available to the client by writing them to a publicly-available location.\r\n\r\n# Usage\r\n\r\nA new setting was added to the config, with three sub-settings.\r\n\r\n- `clientRender`\r\n  - `enabled`: Whether templates are to be made available to the client\r\n  - `outputFormat`: Whether all templates will be merged into a single JS file (`combined`), or each template will be on its own file (`separate`)\r\n  - `outputPath`: The path to where the template files should be written, relative to the public folder. This should be a folder when `outputFormat` is `separate` and a file when `combined`\r\n\r\n# Example\r\n\r\nLet's imagine a site containing two templates: `index.dust` and `article.dust`.\r\n\r\n```html\r\n<!-- index.dust -->\r\n<h1>Latest news:</h1>\r\n\r\n{#articles}\r\n    {> \"partials/article\"}\r\n{/articles}\r\n```\r\n\r\n```html\r\n<!-- article.dust -->\r\n<article class=\"news\">\r\n\t<h2 class=\"news__title\">{title}</h2>\r\n\t<p class=\"news__body\">{body}</p>\r\n</article>\r\n```\r\n\r\nThe initial load will happen entirely on the server, but we can subsequently append new articles to the page, dynamically and re-using the same templates.\r\n\r\nEach template will be made available with the same name as on the server, as the screenshot below shows.\r\n\r\n![screen shot 2016-04-08 at 12 37 43](https://cloud.githubusercontent.com/assets/4162329/14383039/3ab33464-fd8a-11e5-8f0b-713bdf304f2e.png)\r\n\r\nLet me know your thoughts @josephdenne @jimlambie @mingard.\r\n\r\n(Tests to follow if we go ahead with this)"},"comment":{"url":"https://api.github.com/repos/dadi/web/issues/comments/208311321","html_url":"https://github.com/dadi/web/pull/50#issuecomment-208311321","issue_url":"https://api.github.com/repos/dadi/web/issues/50","id":208311321,"user":{"login":"eduardoboucas","id":4162329,"avatar_url":"https://avatars.githubusercontent.com/u/4162329?v=3","gravatar_id":"","url":"https://api.github.com/users/eduardoboucas","html_url":"https://github.com/eduardoboucas","followers_url":"https://api.github.com/users/eduardoboucas/followers","following_url":"https://api.github.com/users/eduardoboucas/following{/other_user}","gists_url":"https://api.github.com/users/eduardoboucas/gists{/gist_id}","starred_url":"https://api.github.com/users/eduardoboucas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eduardoboucas/subscriptions","organizations_url":"https://api.github.com/users/eduardoboucas/orgs","repos_url":"https://api.github.com/users/eduardoboucas/repos","events_url":"https://api.github.com/users/eduardoboucas/events{/privacy}","received_events_url":"https://api.github.com/users/eduardoboucas/received_events","type":"User","site_admin":false},"created_at":"2016-04-11T12:10:17Z","updated_at":"2016-04-11T12:10:17Z","body":"By making a page/route able to return a JSON object in alternative to HTML, you could do the validation on the server and return any error messages that result from the operation as part of the response, which you'd then pass to the client-side template to be displayed. That's one way of doing it without any code duplication.\r\n\r\nUltimately, it would depend on what the interface requires. For example, if you want to validate a field as the user types, it wouldn't be practical to make a round-trip to the server on every keystroke. In that case, you'd probably want to use some client-side validation logic and render just the error message when appropriate (which could itself be a client-side rendered template)."}}