Using HTML template and JQuery.clone()



In a recent proof of concept I was putting together, I needed a way to display different data on the fly, but with the same layout. As it was for a SharePoint 2013 SharePoint hosted app, all I had was Java Script and HTML to perform my task. Originally when I first started to write the code I was building the DIV, SPAN and other objects in the code, line by line. When I was about to start the code for the 3rd section, I thought there must be an easier way.

And there is! Create a template on the HTML page to clone when needed, but have it hidden.

Below is an image of the template if it was visible on the page.


If we take a look at the HTML for it, you will see it just a simple HTML layout. The div with the ID “details” is where we will be cloning the template to in code. (Please note I’m not a designer and there are probably huge mistakes with this. Happy to be corrected).

</pre>
<div id="details"></div>
<div class="hiddenTemplate">
<div id="Template">
<h2><label class="header">This is Header</label></h2>
<div class="buttonDiv"><button class="deleteButton" type="button">Delete</button></div>
<b>ID: </b><span class="itemId">ID</span>

<b>Name: </b><span class="&quot;itemName">Name</span>

<span class="descriptionArea">
<b>Description: </b><span class="itemDescription">Description</span>

</span>
<span class="parentArea">
<b>Parent ID: </b><span class="itemParentID">Parent ID</span>

<b>Parent Name: </b><span class="&quot;itemParentName">Parent Name</span>

</span>
<div class="addItem"><span class="addItemInstruction">Add Items here</span>

<input class="addItemInput" type="text" />
<span class="addButtonSpan"><button class="addButton" type="button">Add</button></span></div>
</div>
</div>
<pre>

Using css I’m able to style and hide the template from the user on the page.

.hiddenTemplate {
display:none;
}
.deleteButton
{
margin-left:0px;
margin-top:2px;
}
.addItem
{
border:1px dotted lightgray
}
.parentArea
{
.display:none;
}

In your JavaScript code, once you have obtained your data you simply grab a copy of the template, clone it using $(‘#Template’).clone(); and then update any details before adding it to the “details” div.

I needed to use the template 4 times and show it slight different for each one, and also depending on values returned. Below is the code for just one of my returned items, however you can see how simple in a loop you could reuse this, or design it differently depending on the data coming back.

 //TermDetails.
 //Get if it is the root term, Term Name and Description.
 var root = termDetails.get_isRoot();
 var termName = termDetails.get_name();
 var termDescription = termDetails.get_description();

//Find template and Clone it.
 var termTemplate = $('#Template').clone();
 //Get the header, and update the text within the clone template.
 termTemplate.find('.header').text("Term Details");
 //Give the template a unique ID, so it can be referenced later in code if needed.
 termTemplate.attr('id', "boxDetails" + termId.toString());

//Show the display button, and give it an on click function.
 termTemplate.find('.deleteButton').show().on('click', function () { removeTerm(termStoreId, groupId, termSetId, termId) });
 //Display Item ID.
 termTemplate.find('.itemId').text(termId.toString());
 //Display Item Name.
 termTemplate.find('.itemName').text(termName);
 //If there is no description don't show it
 if (termDescription == "")
 termTemplate.find('descriptionArea').hide();
 else
 termTemplate.find('itemDescription').text(termDescription.toString());

//If not root, then it has a parent, find out who the parent is.
 var parent;
 if (!root) {
 parent = termDetails.get_parent();
 context.load(parent);
 context.executeQueryAsync(
 function () {
 //success getting parent
 var parentName = parent.get_name();
 var parentId = parent.get_id();
 //Show Parent Area.
 termTemplate.find('.parentArea').show();
 //Display Parent ID.
 termTemplate.find('.itemParentID').text(parentId.toString());
 //Display Parent Name.
 termTemplate.find('.itemParentName').text(parentName);
 }, function () {
 //failed
 console.log("Error obtaining parent details");
 });
 }

//Put instructions for the add button
 termTemplate.find('.addItemInstructions').text("Please enter the name of the Term to add to " + termName);
 //Give input box an ID to reference later
 termTemplate.find('.addItemInput').attr('id', 'createSubTermTextBox');
 //Give button an ID.
 termTemplate.find('.addButton').attr('id', 'createSubTermButton');
 //Change text of button.
 termTemplate.find('.addButton').attr('value', 'Add Term');
 //Give the button an on click function
 termTemplate.find('.addButton').on('click', function () { addSubTerm(termStoreId, groupId, termSetId, termId); });

//Add the template to the details tag.
 $('#details').append(termTemplate);
 

With some additional css the final outcome looks like below.
 

Advertisements