We actually work with the Symfony 2 PHP framework and Twig as a template engine. We think that we could avoid code duplication for the View layer and benefit from progressive enhancement (p-jax).
Current status:
PJAX doesn't handle partial updates of the page layout based on route. Our goal is to implement a system where only some page "fragments" (HTML nodes) would be updated when navigation is handled by Y.App (routing).
In this regard we started to implement a POC at: https://github.com/benjamindulau/PocSfYui/ Javascript can be found here: https://github.com/benjamindulau/PocSfYui/tree/master/src/Acme/PocBundle/Resources/public/js And Y.App initial configuration there: https://github.com/benjamindulau/PocSfYui/blob/master/src/Acme/PocBundle/Resources/views/layout.html.twig#L66
The idea is that when we first load the page, everything is handled server-side (progressive enhancement), meaning that the whole page and page fragments are rendered by the server. For the next requests, which should be performed by Y.App, we defined a JSON format like the following (/photos path response):
{
"title": "MyAwesomeWebsite - Photos", // page <title>,
"fragments": {
"sidebar": "<h2>Sidebar Menu<\/h2><!-- etc.... -->", // ..... maybe an updated menu for active page
"main": "<h2>Photos<\/h2><div id=\"photo-list-container\"><ul id=\"photo-list\"><!-- photo items.... --></ul></div>", // Pre-rendered photo list
},
"templates": {
"photo_item_tpl": "<li data-id=\"{{index}}\"><img src=\"{{url}}\" alt=\"{{title}}\" \/><\/li>" // template used later by Y.App for adding new photos
}
}
Which is basically a "JSONified" version of the current view content (route).
On server side, we detect that the request came from Y.App and instead of rendering our Twig template, we extract "blocks" from it and construct this JSON response containing page fragments that need to be updated + handlebar templates that the client needs for this specific page.
On client side (Y.App):
- we defined a base PageCompositeView which represents the whole page layout, and then a Page2colLeftView which inherit from this and instanciates its own sub-views: SidebarView, MainView, HeaderView, ....
- we wrote a IO module which forges our PJAX-Like requests. We use it instead of "loadContent" (see: https://github.com/benjamindulau/PocSfYui/blob/master/src/Acme/PocBundle/Resources/views/layout.html.twig#L93)
- on first load we call showView and try to "re-connect" our page sub-views to their respective containers (see: https://github.com/benjamindulau/PocSfYui/blob/master/src/Acme/PocBundle/Resources/public/js/views/page.js#L27)
- when navigating in pages, Y.App knows about pages structure.
Say we load directly the "/photos" path in our browser: 1. The server renders the whole page containing a photo list 2. The YUI App creates its PageCompositeView and reconnects each sub-view to its container 3. The YUI App knows that the "MainView" view (which corresponds to the main content) should contain a "PhotoListView" sub-view binded to a "PhotoModelList" model list. So a callback on "/photos" path creates the "PhotoView" instance and reconnects it to its container (rendered by the server).
2 and 3 (especially 3) are done manually.
The POC actually works.
But before going further we'd love to get your advices.
First thing first, what do you think about this POC ?
We actually see pros & cons with this approach.
Our main concern is about how we tweak Y.App to achieve what we want: - A single composite view - On first load, the models are re-hydrated by reading the existing DOM (i.e: when photo list is rendered by the server) - The more we move forward, the more we think that we're missing something about Y.App and that we took it the wrong way ;-)
But the positive side about all this is that we could build a full asynchronous website without so much work.
Our main goal is to keep everything maintenable by providing an "almost-complete" generic solution.
Maybe the main question that emerges from that message would be:
"Are we using Y.App the right way ?" ;-)
So, what do you think ?
Thanks, Cya