Is there any simple way to apply a page template to multiple Apache Sling scripts?
I'm looking for something akin to the JSP 2.0 Tag option. However, I'm using HTL, which doesn't support such tags.
I could, of course, use HTL includes, such as data-sly-include="${'header.html'}, but these would then have to be manually included in every page I then create.
Ideally I'd like to be able to have a master page containing the layout, which is then automatically applied to all pages of specified resource types, leaving a customisable area for content specific to each resource. I'd then be able to limit my add.html, edit.html, html.html (etc) files to include only a block of code for the content section of the page, preventing unnecessary duplication of layout code across multiple files.
I thought I might be able to achieve this by creating a master page resource (e.g. "page"), then setting sling:resourceSuperType on the individual resources but since this acts as a fallback, it'll only kick in if there's no matching script for the sling:resourceType - and there will be such scripts.
You could use a Sling Decorator to wrap your resources so that they always get handled by the common scripts before everything else. This way you can impose the template and include the actual resource to fill in the actual values/blocks/custom scripts.
Another option would be to impose a (nested) content tree where the root points to the template scripts (using JCR type, for example) while the children/content point to the custom scripts (using resource type). This is pretty much what AEM does with cq:Page and its jcr:content.
I ended up using the following approach:
Add a new resource type page
Create a Sightly/HTL template file for the page resource type (/apps/page/html.html); this is the 'master' page template
Include common elements in that template
Within that template, call the 'child' templates by adding the view selector through the following HTL element: <div data-sly-resource="${request.pathInfo # selectors='view', addSelectors=request.requestPathInfo.selectors, requestAttributes=request.requestParameterMap}">
For each sling:resourceType that's to be rendered as a page, add a view subfolder (/apps/example_type/view) and place its HTL templates within that folder (e.g. add.html, html.html)
On each resource that should be rendered with the master template, set sling:resourceSuperType to page
When a request comes in to, for example, /content/example_type_instance.add.html, Sling resolution will therefore try to find a script in /apps/example_type/add.html; there isn't one, so it falls back to the resourceSuperType script in apps/page/html.html, which in turn will use the script in /apps/example_type/view/add.html.
This seems to work for the moment. #Vlad's approach with a Sling ResourceDecorator may be more elegant.
Related
I am learning Rails 5.0, via a tutorial. Learning how to generate view templates, but the term "template" is never explicitly defined. I've searched in the Rails docs, and they seem to mention the word a lot, but also never really define it explicitly.
I know that views are the HTML, CSS associated with what the user sees. But was wondering what is a template and how is it different than a standard webpage?
I don't have an authoritative answer. But this is really rather simple. RoR lets you generate content dynamically. This means, with one template, you could generate different content (html pages). The final html page generated and served by the server is the webpage endusers see. For example, you could have a template show.html.erb with the following line:
<h> Product <%=#product.name%> </h>
From this template, different webpages for each different #product can be generated with that #product's name, depending on the #product variable, which is provided by the controller.
So templates allow you to dynamically generate content and render them as different html webpages.
Being relatively new to MVC I have been struggling for the past several weeks getting my layout to work.
I have managed to get myself really twisted into knots. So instead of trying to explain and unravel my mess perhaps instead someone could explain how I would accomplish the following at a high level.
_Layout this would have all the css js etc. It would also have basic structure.
Of course HTML tags not allowed in code block....each render is in a div.
#RenderPartial(Header)</div>
#RenderBody()</div>
#RenderPartial(Footer)</div>
RenderBody is Index.cshtml and it would be broken into three pieces
#
#Html.Partial(NavMenu, model)</div>
#Html.Partial(SubNavMenu, model)</div>
#Html.Partial(MainContent, model)</div>
I have this basic layout and it looks fine until you click one of the menu items.
The menu items render as:
<a class="k-link" href="/stuffroute">Stuff</a>
That route goes to a controller that returns a view and that navigates away from the above arrangement in Index.cshtml. So I end up with the header, footer, and subdash nav....
So the question is...
How do I route / orchestrate my layout to not lose the differing pieces?
Partials don't do anything for you here. You're essentially asking about how to create SPA (single page application), although in this case your application will have other pages, it's just that the index view will act like a SPA.
That requires JavaScript, specifically AJAX, to make requests to endpoints that will return HTML fragments you can use to replace portions of the DOM with. For example, clicking "Stuff 1" causes an AJAX request to be made to the URL that routes to FooController.GetSubNav([stuff identifier]). That action then would use what was passed to it to retrieve the correct sub-nav and return a partial view that renders that sub-nav. Your AJAX callback will then take this response, select a portion of the DOM (specifically the parent of the sub-nav) and insert the new HTML as its innerHTML.
If you're going to be doing a lot of this, you'll want to make use of some client-side MVC-style JavaScript library, like Angular for example. These make it trivial to wire everything up.
I'm looking to migrate some of my projects from our custom framework into ZF2. In our framework we have one 'global' controller what sets up the page layout, header, gets any data from the database that's needed on every page, and then all other controllers for separate pages extend of of that.
What's the 'Zend' way of doing this? E.g. on every page I need to run a query SELECT html FROM dbcms.adverts and display the html field on every page.
You would create a ViewHelper that gains access to the Database. This access is done by having any DB-Access-Tool you want (TableGateway, Doctrine2, DbAdapter, etc..) and pass this into the ViewHelper.
The ViewHelper then would simply return the HTML-String. And inside your Layout and/or View-Scripts you'd use the ViewHelper in the likes of echo $this->myHtmlViewHelper().
I'm trying to get the hang of the whole asset pipeline thing, and read the guide and several tutorials about them. But one thing that doesn't become quite clear is wether I should view my javascript asset files as a library or a place to put code that is actually run i.e. $(document).ready. Because by default all the javascript files are included, and it would be weird to have several $(document).ready's in there, not to mention that you don't want the $(document).ready function for every page to be run in the first place. What would be the way to go at this? Use my asset files as a library and put actual calls in my views (ugly)? Or is there a better way to do this?
I too ran into this issue. In a large project you can have somebody put code into document ready to, for example, add a click function to each li within a div with class container.
Now we could all argue that the above code would be too generic and of course may affect li tags in other parts of the application, but the bigger the project, the more likely it is that you will run into a conflict like this leading to unexpected behaviour.
I for one am uncomfortable with a whole bunch of document ready functions running for each and every page loaded. My solution is not necessarily the perfect one, but it's one that I have taken up and will share with you.
In the body tag of each page I add data elements signifying the controller and the action. I then have one document ready script that looks for a class named after the controller with the name Ready appended e.g. HomeReady. It will then call a method on this class (presuming it exists) named after the action. So in your asset coffee file you could write:
class #HomeReady
#index: ->
alert("Hello")
#show: ->
alert("Goodbye")
This allows control right down to the action level. When I came across your question I decided to package this solution into a gem as I have already used it in several projects. You can find it at: https://github.com/intrica/rails_document_ready
If you absolutely don't want a certain piece of initialization code to be run unless the current page is a specific controller/action, then you can try adding an empty element on the page with an id built from that info like "posts_index" using these two helpers:
"#{controller_name}_#{action_name}"
Then in your javascript you can wrap the code inside an if statement that checks for the existence of an element with the appropriate id.
edit: Here's an example of the js partial that I mentioned in the comments.
show.html.haml
= render 'map'
map.html.erb (I normally use haml but it's easier to write js in erb)
<script src='http://www.google.com/jsapi' type='text/javascript'></script>
<script type='text/javascript'>
...
</script>
It's probably not as clean as it could be and it doesn't get the benefits of being part of the asset pipeline but I don't mind because it's only something that gets included on a specific page.
The two concepts Partial and Slot seem the same for me. Both of these two features replace placeholders in template with actual markup.
When should I use Partial and when should I use Slot?
The major difference between slots and partials is that the rendering for a given slot resides within a certain template. In opposite, the partial is merely an include of a template into another template.
"Basically, a slot is a placeholder that you can put in any of the view elements (in the layout, a template, or a partial). Filling this placeholder is just like setting a variable. The filling code is stored globally in the response, so you can define it anywhere (in the layout, a template, or a partial). Just make sure to define a slot before including it, and remember that the layout is executed after the template (this is the decoration process), and the partials are executed when they are called in a template."
Examples of ways of using each are:
Title for your page - would probably be placed in a slot (or in the title helper), and you would then in your layout check whether the slot was defined and then show it.
Sidebar items - say you have 3 sidebar "slots", you would then have three slots, for example 'sidebar-1', 'sidebar-2' and 'sidebar-3'. In your template you would then define the slot, which could be rendered using a partial (or even a component) if you wanted.
I hope that clarified it a bit.
A partial comes from a file:
include_partial('thing', $params) will include _thing.php with $params in it's scope.
Slots are not files, but set somewhere else in the template/controller:
slot('title', 'Home Page');
echo '<title>'.slot('title').'</title>'
All you need to know is the Symfony cheat sheet View. Partials, components, slots and component slots (PDF, 45 KB).
You could think of a slot as an OO method definition. Your layout defines slots. The template extends the layout and fills those slots (by overwriting the methods). You can also have a default content for a slot, which is displayed when it's not overwritten.
Partials on the other hand would be like composition. They are a reusable component that templates can access. Roughly they are the equivalent of a simple include statement, but you pass in the variables it uses.
This page does a pretty good job at explaining the concepts: http://www.symfony-project.org/book/1_2/07-Inside-the-View-Layer