Quite a while ago I wrote an article on Liferay's Expandos (on top of which our Custom Attributes (Custom Fields) are built), using the WCM as the runtime for a small app called First Expando Bank.
Since that time the API has undergone slight alterations and so since there was so much interest in it, here is new implementation which does a better job of showing how to use the API by:
- Making less service calls
- Demonstrating Pagination
Here is the updated template:
##
## Do some request handling setup.
##
#set ($companyId = $getterUtil.getLong($request.theme-display.company-id))
#set ($locale = $localeUtil.fromLanguageId($request.locale))
#set ($dateFormatDateTime = $dateFormats.getDateTime($locale))
#set ($renderUrl = $request.render-url)
#set ($pns = $request.portlet-namespace)
#set ($cmd = $getterUtil.getString($request.parameters.cmd))
#set ($cur = $getterUtil.getInteger($request.parameters.cur, 1))
#set ($delta = $getterUtil.getInteger($request.parameters.delta, 5))
#set ($end = $cur * $delta)
#set ($start = $end - $delta)
<h1>First Expando Bank</h1>
##
## Define the "name" for our ExpandoTable.
##
#set ($accountsTableName = "AccountsTable")
##
## Get/Create the ExpandoTable to hold our data.
##
#set ($accountsTable = $expandoTableLocalService.getTable($companyId, $accountsTableName, $accountsTableName))
#set ($accountsTableId = $accountsTable.getTableId())
#if (!$accountsTable)
#set ($accountsTable = $expandoTableLocalService.addTable($companyId, $accountsTableName, $accountsTableName))
#set ($accountsTableId = $accountsTable.getTableId())
#set ($VOID = $expandoColumnLocalService.addColumn($accountsTableId, "firstName", 15)) ## STRING
#set ($VOID = $expandoColumnLocalService.addColumn($accountsTableId, "lastName", 15)) ## STRING
#set ($VOID = $expandoColumnLocalService.addColumn($accountsTableId, "balance", 5)) ## DOUBLE
#set ($VOID = $expandoColumnLocalService.addColumn($accountsTableId, "modifiedDate", 3)) ## DATE
#end
#set ($accountsTableClassNameId = $accountsTable.getClassNameId())
#set ($columns = $expandoColumnLocalService.getColumns($accountsTableId))
##
## Check to see if a classPK was passed in the request.
##
#set ($classPK = $getterUtil.getLong($request.parameters.classPK))
##
## Check if we have received a form submission?
##
#if ($cmd.equals('add') || $cmd.equals('update'))
##
## Let's get the form values from the request.
##
#set ($firstName = $getterUtil.getString($request.parameters.firstName, ''))
#set ($lastName = $getterUtil.getString($request.parameters.lastName, ''))
#set ($balance = $getterUtil.getDouble($request.parameters.balance, 0.0))
#set ($date = $dateTool.getDate())
##
## Validate the params to see if we should proceed.
##
#if ($balance < 50)
Please fill the form completely in order to create an account. The minimum amount of cash required to create an account is $50.
#elseif (!$firstName.equals('') && !$lastName.equals(''))
##
## Check to see if it's a new Account.
##
#if ($classPK <= 0)
#set ($classPK = $dateTool.getDate().getTime())
#end
#set ($VOID = $expandoValueLocalService.addValues($accountsTableClassNameId, $accountsTableId, $columns, $classPK, {'firstName':$firstName, 'lastName':$lastName, 'balance':"$balance", 'modifiedDate':"${date.getTime()}"}))
##
## Show a response.
##
#if ($cmd.equals('update'))
Thank you, ${firstName}, for updating your account with our bank!
#else
Thank you, ${firstName}, for creating an account with our bank!
#end
#else
Please fill the form completely in order to create an account. Make sure to till both first and last name fields.
#end
#elseif ($cmd.equals('delete'))
##
## Delete the specified Row.
##
#if ($classPK > 0)
#set ($VOID = $expandoRowLocalService.deleteRow($accountsTableId, $classPK))
Account deleted!
#set ($classPK = 0)
#end
#elseif ($cmd.equals('edit'))
##
## Edit the specified Row.
##
Editting...
#end
<span style="display: block; border-top: 1px solid #CCC; margin: 5px 0px 5px 0px;"></span>
#if (!$cmd.equals('edit'))
##
## Now we're into the display logic.
##
<input type="button" value="Create Account" onClick="self.location = '${renderUrl}&${pns}cmd=edit';" />
<br /><br />
<table class="taglib-search-iterator">
<tr class="results-header">
<th class="col-1">Account Number</th>
<th class="col-2">First Name</th>
<th class="col-3">Last Name</th>
<th class="col-4">Balance</th>
<th class="col-5">Modified Date</th>
<th class="col-6"><!----></th>
</tr>
##
## Get all the current records in our ExpandoTable. We can paginate by passing a
## "begin" and "end" params.
##
#set ($total = $expandoRowLocalService.getRowsCount($accountsTableId))
#set ($rows = $expandoRowLocalService.getRows($accountsTableId, $start, $end))
#foreach($row in $rows)
#set ($cssClass = 'results-row')
#if ($velocityCount % 2 == 0)
#set ($cssClass = "${cssClass} alt")
#end
#if ($velocityCount == 1)
#set ($cssClass = "${cssClass} first")
#elseif ($velocityCount == $rows.size())
#set ($cssClass = "${cssClass} last")
#end
##
## Get the classPK of this row.
##
#set ($currentClassPK = $row.getClassPK())
#set ($rowValues = $expandoValueLocalService.getRowValues($row.getRowId()))
#set ($values = {})
#foreach ($value in $rowValues)
#foreach ($column in $columns)
#if ($value.columnId == $column.columnId)
#set ($VOID = $values.put($column.name, $value))
#end
#end
#end
#set ($currentFirstName = $values.firstName.string)
#set ($currentLastName = $values.lastName.string)
#set ($currentBalance = $values.balance.double)
#set ($currentModifiedDate = $values.modifiedDate.date)
<tr class="${cssClass}">
<td class="align-left col-1 valign-left">${currentClassPK}</td>
<td class="align-left col-2 valign-middle">${currentFirstName}</td>
<td class="align-left col-3 valign-middle">${currentLastName}</td>
<td class="align-right col-4 valign-middle">${numberTool.currency($currentBalance)}</td>
<td class="align-left col-5 valign-middle">${dateFormatDateTime.format($currentModifiedDate)}</td>
<td class="align-right col-6 valign-middle">
<a href="${renderUrl}&${pns}cmd=edit&${pns}classPK=${currentClassPK}">Edit</a> |
<a href="${renderUrl}&${pns}cmd=delete&${pns}classPK=${currentClassPK}">Delete</a>
</td>
</tr>
#end
#if ($total <= 0)
<tr>
<td colspan="5">No Accounts were found.</td>
</tr>
#end
</table>
<br/>
#if ($total > $delta)
<div style="float: right;">
<div>
#set ($previous = $cur - 1)
#set ($next = $cur + 1)
#if ($previous > 0)
<a href="${renderUrl}&${pns}cur=${previous}" class="previous">‹‹ #language('previous')</a>
#else
<span class="previous">‹‹ #language('previous')</span>
#end
#set ($pagesIteratorBegin = 1)
#set ($pagesIteratorEnd = $total / $delta)
#if (($total % $delta) > 0)
#set ($pagesIteratorEnd = $pagesIteratorEnd + 1)
#end
#foreach ($index in [$pagesIteratorBegin..$pagesIteratorEnd])
#if ($index == $cur)
#set ($pageNumber = "<strong>${index}</strong>")
#else
#set ($pageNumber = $index)
#end
<a href="${renderUrl}&${pns}cur=${index}" class="previous">${pageNumber}</a>
#end
#if ($next > $cur && $next <= $pagesIteratorEnd)
<a href="${renderUrl}&${pns}cur=${next}" class="next">#language('next') ››</a>
#else
<span class="next">#language('next') ››</span>
#end
</div>
</div>
#end
# of Accounts: ${total}
#else
##
## Here we have our input form.
##
#if ($classPK > 0)
##
## Get the account specific values
##
#set ($rowValues = $expandoValueLocalService.getRowValues($companyId, $accountsTableName, $accountsTableName, $classPK, -1, -1))
#set ($values = {})
#foreach ($value in $rowValues)
#foreach ($column in $columns)
#if ($value.columnId == $column.columnId)
#set ($VOID = $values.put($column.name, $value))
#end
#end
#end
#set ($currentFirstName = $values.firstName.string)
#set ($currentLastName = $values.lastName.string)
#set ($currentBalance = $values.balance.double)
#end
<form action="$renderUrl" method="post" name="${pns}fm10">
<input type="hidden" name="${pns}classPK" value="$!{classPK}" />
<input type="hidden" name="${pns}cmd" #if ($classPK > 0) value="update" #else value="add" #end/>
<table class="lfr-table">
<tr>
<td>First Name:</td>
<td>
<input type="text" name="${pns}firstName" value="$!{currentFirstName}" />
</td>
</tr>
<tr>
<td>Last Name:</td>
<td>
<input type="text" name="${pns}lastName" value="$!{currentLastName}" />
</td>
</tr>
<tr>
<td>Balance:</td>
<td>
<input type="text" name="${pns}balance" value="$!{numberTool.format($currentBalance)}" />
</td>
</tr>
</table>
<br />
<input type="submit" value="Save" />
<input type="button" value="Cancel" onclick="self.location = '${renderUrl}'" />
</form>
#end
<br /><br /> Enjoy!

