Injection
Using Views within Views
Views should be created within the context of a single node, generally currentNode
.
For rendering another node, its Component is referenced with <template:module />
.
The following example shows how to get all the child nodes of the current node, and render each of them with their corresponding views:
<c:forEach items="${currentNode.nodes}" var="child">
<template:module node="${child}" view="myView"/>
</c:forEach>
For code repurposing, an addition 'sub' view can be created and included using <template:include />
.
The following example shows how to use the view called short
with format csv
for the current node:
<template:include view="short" templateType="csv"/>
Example
Note the following definitions.cnd
. Employee belongs to a Company, which is selected from choicelist of all available exisiting companies that were created on the current site:
[mynt:employee] > jnt:content, mymix:myCategory, mix:title
- company (weakreference,choicelist[nodes='$currentSite//*;mynt:company']) mandatory
Here is one way to construct a view for Employee:
<h2>${currentNode.properties['jcr:title'].string}</h2>
<h3>Company</h3>
${currentNode.properties.company.node.properties['jcr:title'].string}
This is bad practice. Note how jcr:title
in Company is being referenced from currentNode
. In Jahia, it is not recommended to reference subnode properties directly from currentNode
in this way.
Note the following correct implementation of a view for Employee:
<h2>${currentNode.properties['jcr:title'].string}</h2>
<h3>Company</h3>
<template:module node="${currentNode.properties.company.node}" view="hidden.name" />
The template:module
tag is used to reference a call to a view belonging to a node different from currentNode
. In this case, the node is a property of Employee and references a Company. The view being referenced is called hidden.name
. For views that are not meant to be used directly, their name is prefixed with 'hidden', as demonstrated in this example.
This is what the view for Company, company.hidden.name.jsp
, might look like:
${currentNode.properties['jcr:title'].string}
In essence, the Company Title for Employee is referenced from a call to a view instead of a direct reference from currentNode
. This makes for better programming practice and improves cache efficiency.
Working with Subnodes
A node type definition may include a property that defines its sub-nodes.
Note the following example:
[mynt:employee] > jnt:content, mix:title
[mynt:company] > jnt:content, mymix:myCategory, mix:title
+ * (mynt:employee)
Here, Employee is not made to be a droppable component and so can only be created as the subnode of Company. A button may be included for authors to create Employee subnodes from the Company view in the page composer:
<c:if test="${renderContext.editMode}">
<template:module path="*" nodeTypes="mynt:employee"/>
</c:if>
The view might also include a script for iterating over the Employee nodes for rendering. There are two ways of implementing this:
<c:forEach items="${jcr:getChildrenOfType(currentNode, 'mynt:employee')}" var="employee">
<template:module node="${employee}" view="default" />
</c:forEach>
<c:forEach items="${currentNode.nodes}" var="employee">
<c:if test="${jcr:isNodeType(employee,'mynt:employee')}">
<template:module node="${employee}" view="default" />
</c:if>
</c:forEach>
In the first, the forEach iterates only over the subnodes of type Employee and renders them. For the second, every node is iterated over and then checked with the if
statement for its type.
Exercise: Using Views with Subnodes
- Create a component in Acme Company called "Company Division" with "name" and "address" as properties.
- Company Division can contain several Employees
- When rendered, it displays the name of each employee in the division and a link to access the detail of the employee
- The view must:
- Display a button to allow the authors to create Employee objects as sub nodes of Company Division
- Iterate over the Employee sub nodes and render them