| Page 1 of 1 | [ 8 posts ] |
MarcYUI Contributor
|
Hi,
I've sat down to review the App Framework documentation and it is very good. One thing that I think is missing a bit though is how to deal with server data. The documentation describes at great length the importance of having a server that can deal with the same urls that the pushState creates. However, it does not seem to deal so much, or I don't understand how to deal, with the two or three different sets of data that can therefore be generated by the server: 1. the pushState data, which would normally be Json 2. the HTML response if the user accesses the url directly in the browser 3. the potential use of handlebars as a server response in stead of json? There is some mention of using sync in the Model but I'm not clear how the flow is supposed to work in this case. Is there a natural point where a get to a server is called when rendering a View? Is there any kind of logic to the mapping that is used for this server call? Assuming that the server needs to distinguish between the pushState json response and the full HTML response for a page call. Also if the server generates a full HTML response one would like to avoid the json response from being executed since that would execute the same functions on the server twice. Or do we assume that the json call is always part of the flow and the full HTML path server response should just generate the HTML frame for this to happen? Also it would be interesting to see some suggestions on how to design your server code for maximum flexibility. Below a suggestion from my side based on Spring (but without a full understanding of how App Framework ideally works). Code: /** * Displays an HTML page */ @Controller @RequestMapping("/path") public class StuffController{ @Inject ItemManager itemMgr; public void insertCommonContent(ModelMap model){ model.addAttribute("items", itemMgr.getItems()); } @RequestMapping("/stuff", method=RequestMethod.GET) public String getStuff(ModelMap model){ insertCommonContent(model); model.addAttribute("pageTitle", "Hello there"); model.addAttribute("specialOffers", getSpecialOffers()); } } /** * Returns json */ @Controller public class JsonStuffController extends StuffController{ @RequestMapping("/stuff.json", method=RequestMethod.GET) public @ResponseBody Map<String,Object> getStuff(ModelMap model){ Map<String,Object> resp = new HashMap<String,Object>(); resp.add("items", itemMgr.getItems()); return resp; } } /** * Displays an HTML page optimized for mobile */ @Controller @RequestMapping("/path/mobile") public class MobileStuffController extends StuffController{ @RequestMapping("/stuff", method=RequestMethod.GET) public String getStuff(ModelMap model){ insertCommonContent(model); } } |
|
You should think about data and rendering separately.
A great structure for a web app is to build a RESTful JSON data API, a server-side front end using a web app framework (such as Spring MVC), and a client-side UI using something like the YUI App Framework. This way the server-side front end and the client-side UI can both be "clients" to the data-only API. Additionally, together these three parts form your web app, but they remain decoupled and can therefore rev independently. *Note:* You will probably end up using the same server-side web application framework to build your data-only API. Now you have a standardized interface (JSON via RESTful HTTP) to your backend system(s) and database. The other two parts of your web app work together to form a human UI which communicates with that machine/data API. There server-side front end and client-side UI traditionally differ in two major ways: their lifecycle, and context. The server-side serving all user of the application and its context lasts for the lifecycle of a single HTTP request that its fulfilling. The client-side UI is specific to a particular user and its context is long lived and is around for many requests (thing single-paged app making Ajax calls). Given these differences, fundamentally they are doing the same thing, rendering the data of an application and responding to actions by the user (HTTP request to the server-side, and DOM interactions on the client-side). The patterns you'd use when building a client-side UI with the YUI App Framework are conceptually very similar to what'd you do in a server-side front end: Handle requests for a particular URL and render representation of that resource that represents the current state (data). They both have route handlers which load data (from the data API) into models, then render that data against a template. When using Y.App, you'll want to make sure it can produce the same (or very similar) rendered state in response to the URL changing (pushState) that the server produces when refreshing the page at that same URL. <-- This is the progressive enhancement story. You will see in the two example Y.Apps that I've build the model's `load()`ing data inside the route handlers, this is the same thing you're used to doing on the server: * http://yuilibrary.com/yui/docs/app/app- ... tml#routes * https://github.com/ericf/photosnear.me/ ... app.js#L94 Once the data is loaded in the models, that data is then passed to a Y.View so it can be rendered to a template and then inserted into the page's DOM. Using something like Y.App start to be so similar to what you're already doing on the server that an opportunity to share code between the client and server arises. In the most recent version of Photos Near Me I've done that and it share the exact same Y.Models, Y.ModelLists, and Handlebars templates on the server and client! You can checkout the Open Hours video where I talk about this: http://www.youtube.com/watch?v=Bjs7b8sksO4&hd=1 Framework like Mojito take these code sharing concepts even further by trying to abstract away the difference between code running on the client or server enabling someone to not only share models and templates but also route handling logic. Does this help answer your questions? |
MarcYUI Contributor
|
Hey Eric,
Thanks for the extensive reply. I reviewed your suggestions. Quote: You should think about data and rendering separately. A great structure for a web app is to build a RESTful JSON data API, a server-side front end using a web app framework (such as Spring MVC), and a client-side UI using something like the YUI App Framework. It's interesting to see the use of Mustache as something to share between the client and the server to minimize duplicated code. Working with Spring MVC, this requires a change of perspective. Since we tend to be working with some kind of view technology such as Freemarker, JSP etc. But it's pretty flexible in the kind of data it returns based on REST URLs, JSON, HTML, XML etc. I found various mustache implementation for Spring and Java: e.g. https://github.com/ericdwhite/mustache. ... ing-webmvc I think I'm starting to see the light here. Even if you use JSP as a view technology, you could easily process parts of the page using a mustache template. By including the Mustache template as a Quote: <script id="list-template" type="text/x-handlebars-template"> <p>YUI is brought to you by:</p> <ul> {{#items}} <li><a href="{{url}}">{{name}}</a></li> {{/items}} </ul> </script> into the resulting HTML page, you also provide a handle to further enhance the page using Javascript/JSON when loaded, which I would previously do by duplicating HTML templates in Javascript and parsing them with Y.Lang.sub etc. This also makes coding much easier, since coding HTML through Javascript is a pain. I'm getting excited! Looking forward to seeing more info on this! Cheers, Marc |
MarcYUI Contributor
|
So, after some further investigation, I now realize that Handlebars is an extension of Mustache that in fact makes it incompatible with Mustache and that it has poor Serverside support (unless you use Node.js). Whereas it's dead easy to work with Mustache on the server in Java, it's not at all with Handlebars. There are some sporadic references to Rhino here and there but it all looks like a major headache. Darn.
But wait. Since Handlebars is syntactically compatible with Mustache, one way forward is to use mustache.java and avoid any of the Handlebars extensions. So, assuming one is not ready to throw up ones hands in frustration and quit at this point, the next question is: how to provide a fluid development experience. You want to write a template only once, so that would mean * Having the code mustache code that is used to compile the HTML page Code: <p class="author"> {{#author}} {{firstName}} {{lastName}} {{/author}} </p> * And a Handlebar template, that is used to insert into the HMTL page Code: <script id="list-template" type="text/x-handlebars-template"> <p class="author"> {{#author}} {{firstName}} {{lastName}} {{/author}} </p> </script> * Or compiled to Javascript and deploy (somehow) through the YUI Loader So it would seem to make sense to have a wrapper template that just does Code: <script id="list-template" type="text/x-handlebars-template"> <#include 'mytemplate.mustache'/> </script> Ideally, I want to deploy Handlebar templates through the YUI loader. Including them in the returned HTML just seems a little inelegant, although it would certainly be workable. This means that I need to compile the handlebar templates and make my serverside YUI CombiLoader smart enough to be able to handle handlebar templates. One thing I really *don't* want is to have to execute some compiler action, every time I change a Handlebar template. I want a simple change/save/reload experience. Questions that then come up with me are: * What would be a good way to request pre-compiled handlebar templates through the YUI loader? Do you have to define a YUI component for each handlebar template? * How to create a simple change/save/reload experience in Eclipse? * Assuming one is not on Node.js what are practical suggestions to make it all rock? Marc |
|
mschipperheyn wrote: It's interesting to see the use of Mustache as something to share between the client and the server to minimize duplicated code. Working with Spring MVC, this requires a change of perspective. Since we tend to be working with some kind of view technology such as Freemarker, JSP etc. But it's pretty flexible in the kind of data it returns based on REST URLs, JSON, HTML, XML etc. You might also want to checkout the Mustache.java project: https://github.com/spullara/mustache.java |
|
mschipperheyn wrote: Questions that then come up with me are: * What would be a good way to request pre-compiled handlebar templates through the YUI loader? Do you have to define a YUI component for each handlebar template? * How to create a simple change/save/reload experience in Eclipse? * Assuming one is not on Node.js what are practical suggestions to make it all rock? For precompiling templates, have you checked out the information in the Handlebars user guide? While it's somewhat Node.js specific, the concepts can still be applied to other server-side environments: http://yuilibrary.com/yui/docs/handleba ... -templates You could breakup your templates into separate modules and even combo load them together just like other YUI modules. Pat Cavit has done just that, and describes in code how he's doing it: https://gist.github.com/cb8e25c334fd7c21367c For Photos Near Me, I created one dynamic YUI module to hold all of the precompiled Handlebars templates. In fact I even used a Handlebars template to construct the dynamic module https://github.com/ericf/photosnear.me/ ... handlebars The modules which subclass Y.View simply require the `pnm-templates` modules. Here is the code which handles the HTTP requests for the dynamic templates module: https://github.com/ericf/photosnear.me/ ... js#L79-111 To integrate with Eclipse, you will want to create a builder which is triggered on save and will compile your templates by running a command line script and using this method to precompile your templates: http://yuilibrary.com/yui/docs/handleba ... mmand-line Nothing about these concepts or processes is specific to Node.js, they can implemented in any server-side system. |
MarcYUI Contributor
|
ericf wrote: You might also want to checkout the Mustache.java project: https://github.com/spullara/mustache.java Thanks for all the suggestions. I did have a good look at Mustache.java. Extending it to support Handlebarsjs seems like a fairly time consuming job. At first glance, it seems to be written in a quite functional way. So using the added "tags" would require getting into that processing script, in stead of adding a few classes. Gut reaction would be to rewrite it from scratch while getting some inspiration from mustache.java. I don't have the time for that. Cheers, Marc |
|
But like you said, if you limit yourself to just the Mustache syntax for your templates you'll be fine since Handlebars is a superset.
|
| Page 1 of 1 | [ 8 posts ] |
| You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum |
© 2006-2013 Yahoo! Inc. All rights reserved.
All code on this site is licensed under the BSD License unless stated otherwise.
About This Site · Security Contact Info
Powered by phpBB® Forum Software © phpBB Group