Search in the Documentation:

In practice: Transform a custom HTML form into a Jahia valid form step by step

Let’s take a very basic HTML form as an example

<form action=”your-action.do” method=”post”>

<p>

<label for="firstname">First Name</label>

<input id="firstname" type="text" name="firstname" />

</p>

<p>

<label for="lastname">Last Name</label>

<input id="lastname" type="text" name="lastname" />

</p>

<p><label for="lastname">Gender</label>

<select name="gender" id="gender">

<option value="${valueOption}">Male</option>

<option value="${valueOption}">Female</option>

</select>

</p>

<p>

<label for="happy">Are you happy ?</label></br>

Yes <input type="radio" name="happyness" value="yes"><br/>

No <input type="radio" name="happyness" value="no">

</p>

<div class="divButton"><br />

<input type="submit" tabindex="28" value="<fmt:message key='save'/>" class="button" id="submit" ${disabled}/>

<input type="reset" tabindex="29" value="<fmt:message key='reset'/>" class="button" id="reset" ${disabled}/>

</div>

</form>

To transform that form into a valid form (deployed as a view) that will be creating content in Jahia we will now detail the operations needed.

Add the desired Action

Actions are a powerful mechanism present since Jahia 6.5 to let developers create any kind of operations they need on the server upon submittal of an HTTP request. You will find detailed information about Actions on-line on the Jahia website (http://www.jahia.com).

In the current form we just want to create a new node each time the form is submitted, so we simply specify a path where the nodes should be created (under the form which is our current node), and do not need to use an action, but in a more advanced form usage example you might want to use one (for example to start a workflow or create a user).

<c:url value='${url.base}${currentNode.path}/*'/>

Add hidden fields for Jahia under the <form> tag

We will now use some hidden fields in the form to give Jahia some information about what should happen upon form submittal.

<input type="hidden" name="jcrNodeType" value="jnt:nodeType-to-be-created"/>

<input type="hidden" name="jcrRedirectTo" value="<c:url value='${url.base}${renderContext.mainResource.node.path}'/>"/>

<input type="hidden" name="jcrNewNodeOutputFormat" value="html"/>

<input type="hidden" name="jcrResourceID" value="${currentNode.identifier}"/>

Where:

  • jcrNodeType defines the type of node this form will create on submission
  • jcrRedirectTo defines to which node we want to redirect (you can also specify the template here), here we redirect to the current page
  • jcrNewNodeOutputFormat specify in which format the results will be displayed here html (can be omitted as it is the default value)
  • jcrResourceID specify the identifier of the currently displayed node to allow the cache system to correctly redisplay the form in case of errors.

Protect the form

If your form is going to be used in live mode to allow users to create content, the form must be tokenized and use a captcha at least for non-authenticated users.

<template:tokenizedForm>

<form>

~~~~~~form code~~~~~~

</form>

</template:tokenizedForm>

If you look at the HTML source code in your browser, you will see that the tokenizedForm tag has added an hidden input field in your form containing a UUID that identifies this instance of the form. The UUID is generated by a macro so that the UUID is regenerated each time the form is displayed even if delivered from the cache system.

When a tokenized form is used, you cannot modify any of hidden fields after the rendering of the page.

You also need to add a captcha for at least the non-authenticated users to avoid spamming from fake form submissions. To add a captcha, you need to have an input field named captcha and display the captcha itself using thetemplate:captcha tag.

<c:if test="${not renderContext.loggedIn}">

<p class="field">

<label class="left" for="captcha"><template:captcha/></label>

<input type="text" id="captcha" name="captcha"/>

</p>

</c:if>

Validate the form before submission

Jahia will validate the captcha for you once the form is submitted, and any custom action you integrate may also perform any validation you want, but implementing validations on the client side can reduce errors and risks. To validate form on the client side we recommend you use the JQuery Validate plugin (http://bassistance.de/jquery-plugins/jquery-plugin-validation/)

Here an example of configuring it for the previous form:

<template:addResources type="javascript" resources="jquery.js,jquery.validate.js"/>

<template:addResources type="inlinejavascript">

<script type="text/javascript">

$(document).ready(function() {

$("#newCommentForm").validate({

rules: {

'jcr:title': "required",

<c:if test="${not renderContext.loggedIn}">

pseudo: "required",

captcha: "required"

</c:if>

}

});

});

</script>

</template:addResources>

Please note that this JQuery plugin references fields by their name instead of their id attribute.

On token or captcha errors Jahia will send back the submitted data and refill the form with previously submitted data, so that users do not have to retype everything. All submitted data are stored in a map in the user’s session.

Final form

Our completed form looks like this:

<template:addResources type="javascript" resources="jquery.js,jquery.validate.js"/>

<template:addResources type="inlinejavascript">

<script type="text/javascript">

$(document).ready(function() {

$("#newCommentForm").validate({

rules: {

'jcr:title': "required",

<c:if test="${not renderContext.loggedIn}">

pseudo: "required",

captcha: "required"

</c:if>

}

});

});

</script>

</template:addResources>

<template:tokenizedForm>

<form action="your-action.do" method="post">

<input type="hidden" name="jcrNodeType" value="jnt:mycontacts"/>

<input type="hidden" name="jcrRedirectTo" value="<c:url value='${url.base}${renderContext.mainResource.node.path}'/>"/>

<input type="hidden" name="jcrNewNodeOutputFormat" value="html"/>

<input type="hidden" name="jcrResourceID" value="${currentNode.identifier}"/>

<p>

<label for="firstname">First Name</label>

<input id="firstname" type="text" name="firstname" />

</p>

<p>

<label for="lastname">Last Name</label>

<input id="lastname" type="text" name="lastname" />

</p>

<p><label for="lastname">Gender</label>

<select name="gender" id="gender">

<option value="${valueOption}">Male</option>

<option value="${valueOption}">Female</option>

</select>

</p>

<p>

<label for="happy">Are you happy ?</label></br>

Yes <input type="radio" name="happyness" value="yes"><br/>

No <input type="radio" name="happyness" value="no">

</p>

<c:if test="${not renderContext.loggedIn}">

<p class="field">

<label class="left" for="captcha"><template:captcha/></label>

<input type="text" id="captcha" name="captcha"/>

</p>

</c:if>

<div class="divButton"><br />

<input type="submit" tabindex="28" value="<fmt:message key='save'/>" class="button" id="submit" ${disabled}/>

<input type="reset" tabindex="29" value="<fmt:message key='reset'/>" class="button" id="reset" ${disabled}/>

</div>

</form>

</template:tokenizedForm>