Development Guides Home >> Guide to Package Extensions
Package extensions use Template Toolkit (.tt2) files to display variable forms in the WHM interface. The system injects the template file into the Package Extensions section of WHM's Add a Package, Edit a Package, Create a New Account, and Modify an Account interfaces.
The template file's name must match the default settings file's filename exactly, but include the
.tt2file extension. For example, for thedogdefault settings file, create thedog.tt2template file.You must store the template file in the
/var/cpanel/packages/extensionsdirectory.The system injects template code into a
fieldsettag when it displays in the WHM interface. For this reason, the template file must only return HTML that is valid in afieldsettag.
To prevent the entry of arbitrary or malicious code, the template's form must filter HTML.
This document assumes that you understand basic HTML and Template Toolkit. For more information, read our Guide to Template Toolkit documentation.
The following example is a template file for the dog extension:
<div class="propertyEditor">
<div class="propertyLabel">[% locale.maketext('Dog Species') %]</div>
<div class="propertyValue">
<input id="dog_species" type="text" name="dog_species" value="[% data.defaults.dog_species | html %]">
</div>
</div>
<div class="propertyEditor">
<div class="propertyLabel">[% locale.maketext('Tail Length') %]</div>
<div class="propertyValue">
<input type="radio" id="dogTailLengthTiny" name="dog_tail_length" value="tiny"[% IF data.defaults.dog_tail_length == 'tiny' %] checked="checked"[% END %]>
<label for="dogTailLengthTiny">Tiny</label><br>
<input type="radio" id="dogTailLengthNormal" name="dog_tail_length" value="normal"[% IF data.defaults.dog_tail_length == 'normal' %] checked="checked"[% END %]>
<label for="dogTailLengthNormal">Normal</label><br>
<input type="radio" id="dogTailLengthLong" name="dog_tail_length" value="long"[% IF data.defaults.dog_tail_length == 'long' %] checked="checked"[% END %]>
<label for="dogTailLengthLong">Long</label>
</div>
</div>
<div class="propertyEditor">
<div class="propertyLabel">[% locale.maketext('Spots') %]</div>
<div class="propertyValue">
<input id="dog_spots" type="checkbox" name="dog_spots" value="y"[% IF data.defaults.dog_spots %] checked="checked"[% END %]>
</div>
</div><div class="propertyEditor">
<div class="propertyLabel">[% locale.maketext('Dog Species') %]</div>
<div class="propertyValue">
<input id="dog_species" type="text" name="dog_species" value="[% data.defaults.dog_species | html %]">
</div>
</div>Lines 1 through 6 create a text box with the localized Dog Species label.
Lines 1, 2, and 3 use class selectors to mimic the style of the WHM interface.
Line 4 uses the data.defaults structure to access the default settings file to retrieve the default value for the extension's
dog_speciessetting.Line 4 also filters HTML from the input. The pipe character (
|) represents the FILTER directive.
<div class="propertyEditor">
<div class="propertyLabel">[% locale.maketext('Tail Length') %]</div>
<div class="propertyValue">
<input type="radio" id="dogTailLengthTiny" name="dog_tail_length" value="tiny"[% IF data.defaults.dog_tail_length == 'tiny' %] checked="checked"[% END %]>
<label for="dogTailLengthTiny">Tiny</label><br>
<input type="radio" id="dogTailLengthNormal" name="dog_tail_length" value="normal"[% IF data.defaults.dog_tail_length == 'normal' %] checked="checked"[% END %]>
<label for="dogTailLengthNormal">Normal</label><br>
<input type="radio" id="dogTailLengthLong" name="dog_tail_length" value="long"[% IF data.defaults.dog_tail_length == 'long' %] checked="checked"[% END %]>
<label for="dogTailLengthLong">Long</label>
</div>
</div>Lines 8 through 18 create three radio buttons under the localized Tail Length label. Radio buttons will only submit data if the user selects them.
If the user has not selected a specific radio button, the system will not store data for that choice.
For example, if the user does not select the
tinyandlongradio buttons, but does select thenormalbutton, the system will only save thedog_tail_length=normalsetting to the account or package file.
Lines 8, 9, and 10 use class selectors to mimic the style of the WHM interface.
Lines 11, 13, and 15 use the data.defaults structure to access the default settings file to retrieve default values.
<div class="propertyEditor">
<div class="propertyLabel"><label for="dog_spots">[% locale.maketext('Spots') %]</label></div>
<div class="propertyValue">
<input id="dog_spots" type="checkbox" name="dog_spots" value="y"[% IF data.defaults.dog_spots %] checked="checked"[% END %]>
</div>
</div>Lines 20 through 25 create a checkbox under the localized Spots label. The system saves checkbox values as
0if the checkbox is deselected when the user saves the form.The system interprets any other value as
trueand will select the checkbox when it displays the form.When a user saves a form that contains the template, the system saves unselected checkboxes as
0and selected checkboxes as1.Important:Do not use the values
no,false, or a blank value to indicate a false value in the template or default settings files.Lines 20, 21, and 22 use class selectors to mimic the style of the WHM interface.
Line 23 uses the data.defaults structure to access the default settings file to retrieve default values.
Important:All of the variables that you use in the template file must exist in the default settings file.
The
data.defaultsstructure passes package extension data to your template. To include a package extensions variable in your template, adddata.defaults.to the beginning of the variable name that you used in the default settings file.For example, to create a text input element that allows users to set the value of the
dog_speciesvariable, use the following code:<input type="text" name="dog_species" value="[% data.defaults.dog_species | html %]">The
propertyEditor,propertyLabel,propertyValue, andpropertyCombinedclass selectors provide default behaviors that match the style of the WHM interface.Important:Do not use the
propertyCombinedclass selector with thepropertyLabelorpropertyValueclass selectors in the same template.Use the
propertyCombinedclass selector to create a template with a single column.
This example uses the following code:
<div class="propertyEditor"> <div class="propertyCombined"> <input id="dog_spots" type="checkbox" name="dog_spots" value="y"[% IF data.defaults.dog_spots %] checked="checked"[% END %] >[% locale.maketext('Has Spots') %] </div> </div>Use the
propertyEditor,propertyLabel, andpropertyValueclass selectors to display form elements in two columns:
<div class="propertyEditor"> <div class="propertyLabel"><label for="dog_spots">[% locale.maketext('Has Spots') %]</label></div> <div class="propertyValue"> <input id="dog_spots" type="checkbox" name="dog_spots" value="y"[% IF data.defaults.dog_spots %] checked="checked"[% END %]> </div> </div> <div class="propertyEditor"> <div class="propertyLabel"></div> <div class="propertyValue"> <input id="dog_spots" type="checkbox" name="dog_spots" value="y"[% IF data.defaults.dog_spots %] checked="checked"[% END %] > <label for="dog_spots">[% locale.maketext('Has Spots') %]</label> </div> </div> <div class="propertyEditor"> <div class="propertyLabel"> <input id="dog_spots" type="checkbox" name="dog_spots" value="y"[% IF data.defaults.dog_spots %] checked="checked"[% END %] > <label for="dog_spots">[% locale.maketext('Has Spots') %]</label> </div> <div class="propertyValue"></div> </div>