Yes it's tough if you try to implement Palette or multi select component in Tapestry5. I learned it the hard way, so thought of sharing it.
The example provided by Tapestry is using enum object. Practically we may need to create Select lists for any type of Object. Here find some sample code of one implementation for a users list
First the AssociateUsers.tml
Page Bean
@AuthorizePage
public class AssociateUsers extends SessionContextPageImpl {
@Inject
private ComponentResources resources;
private int selectedButton;
@Persist
private List
users;
@Persist
private List
initialAssociatedusers;
@Inject
private Messages messages;
@Inject
private TypeCoercer typeCoercer;
@Inject
private SelectModelFactory selectModelFactory;
@Property
@Persist
private int staffUserId;
@Property
@Persist
private SelectModel userSelectModel;
@Inject
private FriendManager frndMgr;
@Inject
private UserManager userMgr;
@InjectPage
private UserDashboard userDashboard;
@Property
private FullUserProfile userProfile;
public static final int SELECTED_BUTTON_CANCEL = -1;
public static final int SELECTED_BUTTON_SUBMIT = 1;
@Override
public void onActivate() throws Exception {
super.onActivate();
super.canLoadPage(this.getClass());
}
public void onActivate(int staffUserId) throws Exception {
this.staffUserId = staffUserId;
userProfile = userMgr.getUserProfileOfInvestor(staffUserId);
setupRender();
}
public List
getUsers() {
return users;
}
public void setUsers(List
selected) {
users = selected;
}
public SelectModel getUserModel() throws Exception {
return userSelectModel;
}
public void onSelectedFromCancel() {
selectedButton = SELECTED_BUTTON_CANCEL;
}
void setupRender() throws Exception {
users = new ArrayList
();
initialAssociatedusers = frndMgr.getPeopleListMutualFollowersForUser(staffUserId, getCurrentFirmId());
// invoke service to find all users in the firm
List
usersSelectlist = frndMgr.getPeopleListByFirmId(getCurrentFirmId());
//add alredy associated users to list
for (FriendProfile profile : usersSelectlist) {
if (initialAssociatedusers.contains(profile)) {
users.add(profile);
}
}
//remove present Assign user from list
for (FriendProfile profile : usersSelectlist) {
if (profile.getUserId() == staffUserId) {
usersSelectlist.remove(profile);
break;
}
}
// create a SelectModel from my list of users
userSelectModel = selectModelFactory.create(usersSelectlist, "FullName");
}
@SuppressWarnings("unchecked")
public UserValueEncoder getUserEncoder() {
return new UserValueEncoder(typeCoercer, FriendProfile.class, frndMgr);
}
public Object onSubmitFromAssociateUsers() throws Exception {
switch (selectedButton) {
case SELECTED_BUTTON_CANCEL:
return userDashboard;
default:
//your code based on the selected users
...........................................
return userDashboard;
}
}
}
New Encoder class for your object. In my case it's a user object
public class UserValueEncoder implements ValueEncoder
, ValueEncoderFactory{
@Inject
private FriendManager friendMngr;
@Override
public String toClient(FriendProfile user) {
return String.valueOf(user.getUserId());
}
public UserValueEncoder(TypeCoercer typeCoerce, Class
obj, FriendManager friendMngr) {
this.friendMngr = friendMngr;
}
@Override
public FriendProfile toValue(String id) {
try {
return friendMngr.getFriendProfileByUserId(Integer.parseInt(id));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public ValueEncoder
create(Class type) {
return this;
}
}
App Module changes
public static void contributeValueEncoderSource(MappedConfiguration
ValueEncoderFactory> configuration) {
configuration.addInstance(User.class, UserValueEncoder.class);
}
If you have any questions...please post it as comments.
Ajith.