Well, one more question :s)
At the moment user is able to reach contact details from list of
contact UI screen, where corresponding contact is retreived from db by
primary key and then placed into RequestVar. But as pointed above, I
also would like for user to get contact details directly via url.
Following your advices, I've added loc generated by Menu.param to
SiteMap in Boot.scala:
Boot.scala
---------------------------------------------------------------------------------------------------------------------------------------------------
val contactAddMenuItem
= Menu(Loc("addContact", "contact" :: "add" :: Nil, "Add
Contact"))
val contactViewByNickNameMenuItem
= Menu.param[Contact]("viewContact",
"View Contact",
(nickName : String) => {
logger.debug("Nickname from URL:
%s".format(nickName))
Model
.createNamedQuery[Contact]
("findContactByNickName", "nickName" -> nickName )
.findOne
},
contact => contact.nickName
) / "contact"
val contactMenu
= Menu(Loc("listContacts", "contact" :: "list" :: Nil, "List
Contacts"), contactAddMenuItem, contactViewByNickNameMenuItem)
val menus = homeMenu :: contactMenu :: Nil
LiftRules.setSiteMap(SiteMap(menus : _*))
I'd like to use the same snippet to process contact for both cases: 1)
via id from app; 2) directly via url by nickname. So I added helper
function to Contact.scala which checks whether contact is presented in
Loc.currentValue. If it is not presented, contact is extracted from
RequestVar and code below works as before (I have been using JPA as a
persistence engine, but I'm planning to migrate to Lift's Mapper):
Contact.scala
------------------------------------------------------------------------------------------------------------------------------------------------------
object contactVar extends RequestVar[Contact](new Contact())
def contact = {
val locBoxed = SiteMap.findLoc("viewContact")
(locBoxed : @unchecked) match {
case Full(loc) => {
val contactBoxed = loc.currentValue
(contactBoxed : @unchecked) match {
case Full(c : Contact) => c
case Empty => contactVar.is
}
}
}
}
def add(xhtml : NodeSeq) : NodeSeq = {
def doAdd() = {
if(contact.nickName.length == 0) {
logger.error(() => "Invalid lastName")
S.error("emptyNickName", "The contact's nick name cannot be
blank")
} else {
try {
logger.debug("addContact() - Conact id: " +
contact.contactId)
Model.mergeAndFlush[Contact](contact)
redirectTo("list.html")
} catch {
case ee : EntityExistsException => error("That contact
already exists")
case pe : PersistenceException => error("Error adding
contact"); logger.error(() => "Contact add failed", pe)
}
}
}
val currentId = contact.contactId
bind("contact", xhtml,
"id" -> SHtml.hidden(() => contact.contactId = currentId),
"nickName" -> SHtml.text(contact.nickName, contact.nickName
= _),
"firstName" -> SHtml.text(contact.firstName,
contact.firstName = _),
"lastName" -> SHtml.text(contact.lastName, contact.lastName
= _),
"email" -> SHtml.text(contact.email, contact.email = _),
"birth" -> SHtml.text(dateFormatter.format(contact.birth),
setBirth(_, contact)) % ("id"->"birth"),
"submit" -> SHtml.submit("Save", doAdd)
)
}
Here is the template to display contact details:
/contact/add.html
---------------------------------------------------------------------------------------------------------------------------------------------------
<lift:surround with="default" at="content">
<table>
<lift:ContactOperations.add form="POST">
<contact:id/>
<tr><td>Nick name:</td><td><contact:nickName/></td></tr>
<tr><td>First name</td><td><contact:firstName/></td></tr>
<tr><td>Last name:</td><td><contact:lastName/></td></tr>
<tr><td>Email: </td><td><contact:email/></td></tr>
<tr><td>Birth date:</td><td><contact:birth/></td></tr>
<tr><td colspan="2"><contact:submit/></td></tr>
<script type="text/javascript">
Date.format = 'dd.mm.yyyy';
jQuery(function () {
jQuery('#birth').datePicker({startDate:'00010101'});
})
</script>
</lift:ContactOperations.add>
</table>
</lift:surround>
When contact is accessed from app, details page is successfully
displayed. But when I try to access it via URL, following error
message is returned: The Requested URL '/app/contact/nickname' was not
found on this server. Log shows that corresponding contact was
retreived from database by nickname, but Contact.scala snippet hasn't
been reached.
How do you think, what the reason of this error is?
Thank you.