基于Seam框架关联对象选择

[原创于:http://happydev.iteye.com]


实现对象选择可以直接通过下拉选择框的方式来选择,但这种选择不适合数据量较大的对象选择。

而在企业的Web开发中,经常会用到对关联对象的单选或多选,而关联对象的数据量往往不是下拉选择框可以展现的。

本文提出了一个较为通用的关联对象选择方案。


一、一个较为通用的关联对象选择方案要解决的主要问题

  1. 可能是单选,也可能会是多选;
  2. 将对象进行“可选择对象”的封装,以支持是否选中状态的维护;
  3. 待选对象的数据查询;
  4. 选择时表现层界面viewId的配置;
  5. 选择后返回的viewId的配置;


二、基础框架设计

/**
 * 可选择对象封装模板
 * @author happydev
 *
 * @param <T>
 */
public class SelectableItem <T>{
	public SelectableItem(boolean selected, Object id, String itemInfo, T item){
		this.selected = selected;
		this.id = id;
		this.itemInfo = itemInfo;
		this.item = item;
	}
	/**
	 * 是否已被选择
	 */
	private boolean selected = false;
	
	public boolean isSelected() {
		return selected;
	}

	public void setSelected(boolean selected) {
		this.selected = selected;
	}
	private Object id;
	
	private String itemInfo;
	
	private T item;

	public Object getId() {
		return id;
	}

	public void setId(Object id) {
		this.id = id;
	}

	public String getItemInfo() {
		return itemInfo;
	}

	public void setItemInfo(String itemInfo) {
		this.itemInfo = itemInfo;
	}

	public T getItem() {
		return item;
	}

	public void setItem(T item) {
		this.item = item;
	}

}

/**
 * 对象选择基础封装模板类
 * @author happydev
 *
 * @param <T>
 */
public abstract class BaseSelector<T> {
	@In
	EntityManager entityManager;
	
	private String ret;
	protected String selIds;
	private boolean submited = false;
	private boolean selectOne = false;
	
	/**
	 * 选择复选框ajax事件,处理选中或取消操作
	 * @param item
	 */
	public void onChange(SelectableItem<T> item){
		if (selectOne && item.isSelected()){
			//如果是单选,则要将已选中的其它项取消
			for (SelectableItem<T> t : selectableItems){
				if (t.isSelected() && t != item){
					t.setSelected(false);
				}
			}
		}
	}
	
	/**
	 * 开始单个对象选择
	 * @param ret,选择结束后需要返回的viewId
	 * @param selIds,已被的对象id字符串,用','分隔
	 * @return,返回选择页面的viewId
	 */
	public String startSelOne(String ret, String selIds){
		selectOne = true;
		return startSel(ret, selIds);
	}
	/**
	 * 开始多个对象选择
	 * @param ret,选择结束后需要返回的viewId
	 * @param selIds,已被的对象id字符串,用','分隔
	 * @return,返回选择页面的viewId
	 */
	public String startSelMany(String ret, String selIds){
		selectOne = false;
		return startSel(ret, selIds);
	}
	
	public String startSel(String ret, String selIds){
		this.ret = ret;
		this.selIds = selIds;
		submited = false;
		return getViewId();
	}
	
	/**
	 * 抽象方法,返回选择页面的viewId
	 * @return
	 */
	protected abstract String getViewId();
	
	/**
	 * 选择结束
	 * @return,选择结束后需要返回的viewId
	 */
	public String ok(){
		if (ret == null || ret.length() < 1){
			return "/welcome/welcome.xhtml";
		}
		submited = true;
		return ret;
	}
	/**
	 * 选择取消
	 * @return,选择结束后需要返回的viewId
	 */
	public String cancel(){
		if (ret == null || ret.length() < 1){
			return "/welcome/welcome.xhtml";
		}
		selectableItems = null;//清空
		return ret;
	}
	/**
	 * 抽象方法,取得对象的标签(名称)
	 * @param obj
	 * @return
	 */
	protected abstract String getObjectName(T obj);
	/**
	 * 抽象方法,取得对象的Id
	 * @param obj
	 * @return
	 */
	protected abstract Object getObjectId(T obj);
	
	/**
	 * 取得已被选择的Id字符串,用','分隔
	 */
	public String getSelectedStr(){
		 List<T> l = getSelectedList();
		 StringBuilder sb = new StringBuilder();
		 for (int i = 0; i < l.size() ; i++){
			 sb.append(getObjectName(l.get(i)));
			 if ( i != l.size() -1){
				 sb.append(",");
			 }
		 }
		 return sb.toString();
	}

	/**
	 * 取得已被选择的对象列表
	 * @return
	 */
	public List<T> getSelectedList(){
		List<T> l = new ArrayList<T>();
		for (SelectableItem<T> item : getSelectableItems()){
			if (item.isSelected()){
				l.add(item.getItem());
			}
		}
		return l;
	}
	
	private List<SelectableItem<T>> selectableItems = null;
	
	private void init(){
		List<Long> l_selIds =new ArrayList<Long>();
		if (selIds != null && selIds.length() > 0){
			String[] arr = selIds.split(",");
			if (arr != null){
				for (String id : arr){
					l_selIds.add(Long.parseLong(id));
				}
			}
		}
		List<T> list = getAllObjectToSelect();
		for (T p : list){
			selectableItems.add(new SelectableItem<T>(l_selIds.contains(getObjectId(p)), getObjectId(p),getObjectName(p),p));
		}
	}
	/**
	 * 抽象方法,取得所有可被选择的对象列表
	 * @return
	 */
	protected abstract List<T> getAllObjectToSelect();
	
	public List<SelectableItem<T>> getSelectableItems() {
		if (selectableItems == null){
			selectableItems = new ArrayList<SelectableItem<T>>();
			init();
		}
		return selectableItems;
	}

	public boolean isSubmited() {
		return submited;
	}

	public void setSubmited(boolean submited) {
		this.submited = submited;
	}
	public boolean isSelectOne() {
		return selectOne;
	}


}
 

  

三、具体的实现示例

角色选择器具体的实现代码:

@Name("roleSelector")
@Scope(value = ScopeType.CONVERSATION)
public class RoleSelector extends BaseSelector<Role>{
	@Override
	protected List<Role> getAllObjectToSelect() {
		return entityManager.createQuery("select o from Role o").getResultList();
	}

	@Override
	protected Object getObjectId(Role obj) {
		return obj.getId();
	}

	@Override
	protected String getObjectName(Role obj) {
		return obj.getRoleName();
	}

	@Override
	protected String getViewId() {
		return "/f_sel/role_sel.xhtml";
	}

}

 


角色选择页面代码:

		<s:div styleClass="message" id="selectedStr">
			<h:outputText value="当前选中(单选):#{roleSelector.selectedStr}" rendered="#{roleSelector.selectOne}" />
			<h:outputText value="当前选中(多选):#{roleSelector.selectedStr}" rendered="#{not roleSelector.selectOne}" />
		</s:div>
		<h:form id="selectForm">
            <rich:datascroller align="left" for="peopleList" maxPages="20" rendered="#{roleSelector.selectableItems.size>20}"/>
            <rich:spacer height="30" rendered="#{roleSelector.selectableItems.size>20}"/>
            <rich:dataTable width="100%" id="peopleList" rows="20" columnClasses="col"
                value="#{roleSelector.selectableItems}" var="item">
                <f:facet name="header">
                    <rich:columnGroup>
                        <h:column>
                            <h:outputText styleClass="headerText" value="选择" />
                        </h:column>
                        <h:column>
                            <h:outputText styleClass="headerText" value="角色名称" />
                        </h:column>
                    </rich:columnGroup>
                </f:facet>

                <h:column>
					<h:selectBooleanCheckbox value="#{item.selected}">
						<a4j:support event="onclick" reRender="selectedStr,selectForm" action="#{roleSelector.onChange(item)}"/>
					</h:selectBooleanCheckbox>
                </h:column>
                <h:column>
					<h:outputText value="#{item.item.roleName}" />
	            </h:column>
            </rich:dataTable>
			<div class="actionButtons">
				<h:commandButton value="确定" action="#{roleSelector.ok}" styleClass="buttonStyle">
					<s:conversationId/>
				</h:commandButton>
				<h:outputText value="&#160;&#160;" />
				<s:button value="取消" action="#{roleSelector.cancel}" styleClass="buttonStyle"/>
			</div>
        </h:form>

 用户编辑界面中分配角色的链接代码:

					<s:decorate template="/layout/display.xhtml">
						<ui:define name="label">分配角色</ui:define>
						<h:outputText value="#{userHome.instance.getAllRoleStr()}" rendered="#{not roleSelector.submited}" />
						<h:outputText value="#{roleSelector.selectedStr}" rendered="#{roleSelector.submited}" />
						<h:outputText value=" | " />
						<h:commandLink action="#{roleSelector.startSelMany('/f_sys/user.xhtml', userHome.instance.getAllRoleIds())}" view="/f_sel/role_sel.xhtml" value="选择">
							<s:conversationId/>
						</h:commandLink>
					</s:decorate>

 

在用户对象保存时对所选择角色的保存:

		if (roleSelector.isSubmited()) {
			List<Role> l = roleSelector.getSelectedList();
			instance.setRoles(l);
		}

 







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值