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.
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
@Persist
private List
@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
return users;
}
public void setUsers(List
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
//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
@Inject
private FriendManager friendMngr;
@Override
public String toClient(FriendProfile user) {
return String.valueOf(user.getUserId());
}
public UserValueEncoder(TypeCoercer typeCoerce, Class
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
return this;
}
}
App Module changes
public static void contributeValueEncoderSource(MappedConfiguration
configuration.addInstance(User.class, UserValueEncoder.class);
}
If you have any questions...please post it as comments.
Ajith.