`
dengyin2000
  • 浏览: 1208131 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

T5 技巧 2:为Grid组件的每一行增加“删除/修改”链接。

阅读更多
现在正在使用T5开发一个小项目。 因为现在T5还正处于发展中。 而且没有像T4一样有许多的文档。 和例子(Workbench, Vlib)。 所以我会把在这个开发中遇到的一些问题记录下来。

记得在T4中是使用一组字符串来作为table columns。 为了加上删除/修改按钮的话,我们就只要加上"!operation" 这样的字符串, 然后用block render td就行了。但是到了T5中。 并没有提供这样的属性。

在看了Grid组件的参数后。 我们发现model 这个参数。 毫无疑问这个参数是用来定义Bean中要显示的列, 是否排序, 显示的顺序 等等。  具体可以看org.apache.tapestry.beaneditor.BeanModel。org.apache.tapestry.services.BeanModelSource.  org.apache.tapestry.beaneditor.PropertyModel. 这些接口和他们的实现类。

那我们要怎样增加这样的“删除/修改”列呢? 因为column必须是要在Bean中的一个property。 所以最直接的方法是在Bean中增加这样的一个假的属性。  比如。

class User {

  private int id;
  private String name;
  
  // add a fake property. However this property shouldn't use except in grid render.
  private String operationColumn;

    
  //...............other properties...........

    //  .................getter/setter methods

}



<t:parameter t:name="operationColumnCell">
					<a t:type="ActionLink" t:id="deleteLink" context="currentRow.id">删除</a>
				</t:parameter>


ok.  这样我们就实现了这个“删除/修改”列。

但是大家可能都会觉得这样不爽。因为operationColumn污染了我们的User类。

下面介绍种不污染的方法。

我们还是要从model这个参数下手。。

我们需要build一个beanModel

package com.javaeye.dengyin2000.gtts.tapestry;



import java.lang.annotation.Annotation;



import org.apache.tapestry.PropertyConduit;



public class OperationPC implements PropertyConduit {

	public Object get(Object arg0) {

		return "";

	}



	public Class getPropertyType() {

		return String.class;

	}



	public void set(Object arg0, Object arg1) {

	}



	public <T extends Annotation> T getAnnotation(Class<T> arg0) {

		return null;

	}

}




public static BeanModel buildDriverBeanModel(BeanModelSource beanModelSource, ComponentResources componentSources){
		if (driverBeanModel == null){
			
			PropertyConduit operationPC = new OperationPC();
			
			driverBeanModel = beanModelSource.create(Driver.class, false, componentSources);
			driverBeanModel.remove("id", "sex", "photo", "address", "sexType", "national");
			driverBeanModel.get("name").label("姓名").order(0);
			driverBeanModel.get("idCard").label("身份证").order(1);
			driverBeanModel.get("telNo").label("电话号码").order(2);
			driverBeanModel.get("carNo").label("车牌号码").order(3);
			driverBeanModel.get("carLong").label("车长(米)").order(4);
			driverBeanModel.get("carWidth").label("车宽(米)").order(5);
			driverBeanModel.get("carHeight").label("车高(米)").order(6);
			
			[color=red][b]driverBeanModel.add("operation", operationPC).label("操作").order(7).sortable(false);[/b][/color]
		}
		return driverBeanModel;
	}



在 page 类。


      @Inject
	private BeanModelSource beanModelSource;
	@Inject
	private ComponentResources componentSources;
        ..........................................
	public BeanModel getDriverBeanModel(){
		return MiscUtils.buildDriverBeanModel(beanModelSource, getComponentSources());
	}   

  

html template:

<table t:id="driverGrid" t:type="Grid" model="driverBeanModel" source="driverSource" row="currentRow" empty="nodata" pagerPosition="bottom" rowsPerPage="12" class="xx">
[color=red][b]				<t:parameter t:name="operationCell">
					<a t:type="ActionLink" t:id="deleteLink" context="currentRow.id">删除</a>
				</t:parameter>[/b][/color]
			</table>




ok。

参考:http://www.nabble.com/T5---Adding-modify-delete-actions-to-a-Grid-t3370935.html#a9379935
分享到:
评论
32 楼 lococode 2007-09-20  
dengyin2000 写道
lococode 写道
to:dengyin2000
关于标题所说的给Grid增加操作一列的问题,lz做法是一种方法,但是每个不同的grid都要buildDriverBeanModel一下,是否太复杂了?我们的做法是,每个页面有需要的话,会有一个form类,这里可以在Bean中的一个property,因为我们一开始就把hiernate实体类和页面需要的对象分开的。所以不存在污染bean的问题,而且这样更明确form类的功能。不过model.remove()还是需要用的。
关于Grid分页的实现,对于lz的实现方式,有几点不同意的地方:分页组件BussnissService 存在依赖的的关系,分页组件依赖hsql。
我的做法虽然让我自己现在还是不太满意,但是,至少,可以在一定程度上更加通用。
^_^!


有没有必要多加一个Form对象。  GridDataSource当然需要关联invoke bussniss Service 方法。 你可以说说你是怎样做的。你说hsql不应该出现, 你当然可以把hsql放到service方法中。  当然如果很多domain的话, 那么就有许多findXXX的方法了。


1.一个Pager对象,典型如下:
private List<T> elements;
private int itemAmount;
private int currentPageIndex;
private int pageSize;
public int getXXX
...
public void setXXX
.....

2.一个GridSourceModel 接口,留个具体的业务操作实现,典型代码如下:
//public Pager<T> getCurrentPager();
public Pager<T> getCurrentPager(int pageSize,int pageNo);
//public void setCurrentPager(Pager<T> pager);

3.重新实现:GridDataSource
此中对象为
private final Pager<T> _pager;
而不是ListGridDataSource中的。
private final List _list;
4.contributeTypeCoercer
。。。。。

5.use:
items = new GridSourceModel<XXXObject>() {

      public Pager<XXXObject> getCurrentPager(int pageSize, int pageNo) {
			Pagination<XXXObject1> pus = manager.findXXX(XXx,pageSize,pageNo);
			Pager<XXXObject> pager = getPager(pus);//Pagination -> Pager
			return pager;
		}
};
31 楼 dengyin2000 2007-09-14  
lococode 写道
to:dengyin2000
关于标题所说的给Grid增加操作一列的问题,lz做法是一种方法,但是每个不同的grid都要buildDriverBeanModel一下,是否太复杂了?我们的做法是,每个页面有需要的话,会有一个form类,这里可以在Bean中的一个property,因为我们一开始就把hiernate实体类和页面需要的对象分开的。所以不存在污染bean的问题,而且这样更明确form类的功能。不过model.remove()还是需要用的。
关于Grid分页的实现,对于lz的实现方式,有几点不同意的地方:分页组件BussnissService 存在依赖的的关系,分页组件依赖hsql。
我的做法虽然让我自己现在还是不太满意,但是,至少,可以在一定程度上更加通用。
^_^!


有没有必要多加一个Form对象。  GridDataSource当然需要关联invoke bussniss Service 方法。 你可以说说你是怎样做的。你说hsql不应该出现, 你当然可以把hsql放到service方法中。  当然如果很多domain的话, 那么就有许多findXXX的方法了。
30 楼 lococode 2007-09-14  
to:dengyin2000
关于标题所说的给Grid增加操作一列的问题,lz做法是一种方法,但是每个不同的grid都要buildDriverBeanModel一下,是否太复杂了?我们的做法是,每个页面有需要的话,会有一个form类,这里可以在Bean中的一个property,因为我们一开始就把hiernate实体类和页面需要的对象分开的。所以不存在污染bean的问题,而且这样更明确form类的功能。不过model.remove()还是需要用的。
关于Grid分页的实现,对于lz的实现方式,有几点不同意的地方:分页组件BussnissService 存在依赖的的关系,分页组件依赖hsql。
我的做法虽然让我自己现在还是不太满意,但是,至少,可以在一定程度上更加通用。
^_^!
29 楼 lococode 2007-09-14  
to:dengyin2000
第一眼看了你的  tapestry-grid.png 图,我吓了一跳,怎么谁把我们的项目的截图发出来了,仔细一看,哦,只是用了同一个html样式模板。

我们基于 Tapestry5.0.4 + spring + hibernate 基本一个项目做完了,有不少收获,但是 发现Tapestry 5 还是有不少问题的,也许由于时间的问题,不少问题我还未来的及解决;想在项目结束后,再好好的研究下。希望能共同学习。
28 楼 dengyin2000 2007-09-06  
match927 写道
那里有PropertyConduit类的API
public Object get(Object arg0) ;
  
    public Class getPropertyType() ;
  
    public void set(Object arg0, Object arg1) ;
  
    public <T extends Annotation> T getAnnotation(Class<T> arg0) ;

这几个方法是干什么的?
多谢


你看了这个class 的java doc吗?  不要跟我说你看不懂英语。

/**
 * Used to read or update the value associated with a property. A PropertyConduit provides access to
 * the annotations on the underlying getter and/or setter methods.
 */
public interface PropertyConduit extends AnnotationProvider
{
    /**
     * Reads the property from the instance.
     * 
     * @param instance
     *            object containing the property
     * @return the current value of the property
     */
    Object get(Object instance);

    /**
     * Changes the current value of the property.
     * 
     * @param instance
     *            object containing the property
     * @param value
     *            to change the property to
     */
    void set(Object instance, Object value);

    /** Returns the type of the property read or updated by the conduit. */
    Class getPropertyType();
}
27 楼 dengyin2000 2007-09-06  
match927 写道
to:all

若User对象中有个日期型的变量,它在 grid 中未展示,应该怎么处理呢?


你可以象上面那样自定义Date column的输出。   在你的page中定义一个方法  使用DateFormat格式化输出。。
26 楼 match927 2007-09-05  
那里有PropertyConduit类的API
public Object get(Object arg0) ;
  
    public Class getPropertyType() ;
  
    public void set(Object arg0, Object arg1) ;
  
    public <T extends Annotation> T getAnnotation(Class<T> arg0) ;

这几个方法是干什么的?
多谢
25 楼 match927 2007-09-05  
to:all

若User对象中有个日期型的变量,它在 grid 中未展示,应该怎么处理呢?
24 楼 match927 2007-08-29  
to:dengyin2000
非常感谢,正确的应该是:
<t:parameter t:name="${property}Cell">
<a t:type="ActionLink" t:id="deleteLink" context="currentRow.id">删除</a>
</t:parameter>
23 楼 match927 2007-08-29  
to:dengyin2000
非常感谢,正确的应该是:
<t:parameter t:name="[color=red]${property}Cell[/color]">
<a t:type="ActionLink" t:id="deleteLink" context="currentRow.id">删除</a>
</t:parameter>
22 楼 dengyin2000 2007-08-28  
<t:parameter t:name="${property}ColumnCell"> 
                     <a t:type="ActionLink" t:id="deleteLink" context="currentRow.id">删除</a> 
                 </t:parameter>
21 楼 match927 2007-08-28  
大家帮我看下,为什么链接不出来,我想在grid建个链接,谢谢
		<table t:type="grid" source="persons" rowsPerPage="5" row="person">
			<t:parameter t:name="name">
				<t:ActionLink t:id="view" context="person.name">${person.name}</t:ActionLink>				
			</t:parameter>
		</table>

public class Person {
    private String name;
    private int age;
    
    public Person()
    {
    	this.name = "aspire";
    	this.age = 2008;
    }
    
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
    
    
}

public class Start {

	private Person person;

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}
	
	private Person[] persons;

	public Person[] getPersons() {
		if ( null == persons)
		{
			persons = new Person[]{new Person(), new Person()};
		}
		return persons;
	}

	public void setPersons(Person[] persons) {
		this.persons = persons;
	}
	
	
}
20 楼 dengyin2000 2007-08-25  
BussnissService  这个是业务Service 类。  给你也没有用。

service.pagedQuery  是根据startIndex endIndex 去数据库拿一页的数据。

BasePage 是我写的一个基类。
19 楼 hitalang 2007-08-25  
看了你的文章,我非常感谢你的慷慨相授,我由于初学tapestry5,而且t4没有学过,t5刚刚学习,很多都是看网友的文章之后修改得来的,你的也被我“抄袭了”,脸红呀,可是好奇心促使我还想看更多的东西,你这个是t5下的吗,public class Drivers extends BasePage 好像是t4的,
另外,import com.javaeye.dengyin2000.gtts.genericdao.Page;  
import com.javaeye.dengyin2000.gtts.service.BussnissService; 这两个类,能贴出来吗,谢谢 
18 楼 hitalang 2007-08-25  
使用默认的grid不行吗???
17 楼 dengyin2000 2007-08-25  
hitalang 写道
非常感谢你的分享,我在用grid控件,页面为典型的主/从查询页面,从主传输参数过来到从,从页面用grid,结果也能够查出来,但是分页出了问题,就是说第一页码,可以有结果,但是点击第二页时候,没有显示,搂主能不能帮助解决一下,谢谢


我不知道你是怎样实现GridDataSource的。。

我贴下我的吧。
package com.javaeye.dengyin2000.gtts.utils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.tapestry.beaneditor.PropertyModel;
import org.apache.tapestry.grid.GridDataSource;

import com.javaeye.dengyin2000.gtts.domain.Driver;
import com.javaeye.dengyin2000.gtts.genericdao.Page;
import com.javaeye.dengyin2000.gtts.service.BussnissService;

public class DriverGridDataSource implements GridDataSource {

	private String nameQueryString;
	
	private int pageSize;
	
	private BussnissService service;
	
	private int totalCount;
	
	private Map<Integer, Driver> currentDatas = new HashMap<Integer, Driver>();
	
	public DriverGridDataSource(String string, int pageSize, BussnissService service){
		this.nameQueryString = string;
		this.pageSize = pageSize;
		this.service = service;
	}
	
	public int getAvailableRows() {
		if (totalCount == 0)
			this.totalCount = service.getDomainsCount(getHqlString(), getParams());
		return totalCount;
	}

	public Class getRowType() {
		return Driver.class;
	}

	public Object getRowValue(int index) {
		return currentDatas.get(index);
	}


	@SuppressWarnings("unchecked")
	public void prepare(int startIndex, int endIndex, PropertyModel sortModel,
			boolean ascending) {
		Page page = null;
		if (sortModel == null)
			page = service.pagedQuery(getHqlString(), startIndex, pageSize, null, false, getParams(), this.totalCount);
		else
			page = service.pagedQuery(getHqlString(), startIndex, pageSize, sortModel.getPropertyName(), ascending, getParams(),this.totalCount);
		List<Driver> result = (List<Driver>) page.getResult();
		currentDatas.clear();
		for(int i=0; i<result.size(); i++){
			currentDatas.put(startIndex+i, result.get(i));
		}
	}
	
	private String getHqlString(){
		String hql = "from Driver where 1=1";
		if (StringUtils.isNotBlank(nameQueryString)){
			hql = hql + " and name like :name";
		}
		return hql;
	}

	private Map<String, Object> getParams(){
		Map<String, Object> params = new HashMap<String, Object>();
		if (StringUtils.isNotBlank(nameQueryString)){
			params.put("name", "%" + nameQueryString + "%");
		}
		return params;
	}

	public void setTotalCount(int totalCount) {
		this.totalCount = totalCount;
	}
	
	
}



package com.javaeye.dengyin2000.gtts.pages.basicinformation;

import java.util.ArrayList;
import java.util.List;

import org.apache.tapestry.Block;
import org.apache.tapestry.annotations.Component;
import org.apache.tapestry.annotations.Inject;
import org.apache.tapestry.annotations.Persist;
import org.apache.tapestry.beaneditor.BeanModel;
import org.apache.tapestry.corelib.components.Grid;
import org.apache.tapestry.grid.GridDataSource;
import org.apache.tapestry.services.BeanModelSource;

import com.javaeye.dengyin2000.gtts.base.BasePage;
import com.javaeye.dengyin2000.gtts.domain.Driver;
import com.javaeye.dengyin2000.gtts.utils.DriverGridDataSource;
import com.javaeye.dengyin2000.gtts.utils.MiscUtils;

public class Drivers extends BasePage {
	
	@Inject
	private BeanModelSource beanModelSource;
	
	@Inject
	private Block nodata;
	
	@Component(id="driverGrid")
	private Grid driverGrid;
	
	private String driverName;
	
	private Driver currentRow;
	
	@Persist
	private GridDataSource dataSource;

	public String getDriverName() {
		return driverName;
	}

	public void setDriverName(String driverName) {
		this.driverName = driverName;
	}
	
	public BeanModel getDriverBeanModel(){
		return MiscUtils.buildDriverBeanModel(beanModelSource, getComponentSources());
	}
	
	public GridDataSource getDriverSource(){
		if (dataSource == null) {
			dataSource = new DriverGridDataSource(getDriverName(), driverGrid.getRowsPerPage(), getBussnissService());
		}
		 // fouce the grid to refetch the count;  
		 ((DriverGridDataSource)dataSource).setTotalCount(0);
		 return dataSource;
	}
	
	void onActionFromDeleteLink(int driverId){
		List<Integer> deleteIds = new ArrayList<Integer>();
		deleteIds.add(driverId);
		getBussnissService().deleteDrivers(deleteIds);
		setMessage("删除成功!");
	}

	public Block getNodata() {
		return nodata;
	}

	public Driver getCurrentRow() {
		return currentRow;
	}

	public void setCurrentRow(Driver currentRow) {
		this.currentRow = currentRow;
	}
}

16 楼 hitalang 2007-08-25  
非常感谢你的分享,我在用grid控件,页面为典型的主/从查询页面,从主传输参数过来到从,从页面用grid,结果也能够查出来,但是分页出了问题,就是说第一页码,可以有结果,但是点击第二页时候,没有显示,搂主能不能帮助解决一下,谢谢
15 楼 hitalang 2007-08-23  
谢谢,能不能讲讲下拉框,。。。
14 楼 dengyin2000 2007-08-23  
match927 写道
TO:  dengyin2000

能否整理个完整的"为Grid组件的每一行增加“删除/修改”链接"。
非常感谢。


有哪里不懂?  我应该算讲得比较详细吧,。 
13 楼 match927 2007-08-23  
TO:  dengyin2000

能否整理个完整的"为Grid组件的每一行增加“删除/修改”链接"。
非常感谢。

相关推荐

Global site tag (gtag.js) - Google Analytics