Tapestry4中是不是控件定义与放置位置有关
Tapestry4中是否控件定义与放置位置有关?
环境:T4
Home.html
<html><body jwcid="@Body">
<table width="246" border="0" cellpadding="0" cellspacing="0" align="center">
<form jwcid="submitForm">
<tr><td width="219" height="16" valign="top">
input1<input type="text" name="textfield" jwcid="input1"/>
</td></tr>
<tr><td height="23" valign="top">
<input type="submit" name="Submit2" jwcid="submit1"/>
</td></tr>
<tr><td height="21" valign="top">
<input type="submit" name="Submit22" jwcid="submit2"/>
</td></tr>
<tr><td height="29" colspan="2" valign="top">
input2<input type="text" name="textfield22" jwcid="input2"/>
</td></tr>
</form>
</table>
</body></html>
Home.page
<component id="submitForm" type="Form"/>
<component id="input1" type="TextField">
<binding name="value" value="input1"/>
</component>
<component id="input2" type="TextField">
<binding name="value" value="input2"/>
</component>
<component id="submit1" type="Submit">
<binding name="listener" value="listener:submit1"/>
</component>
<component id="submit2" type="Submit">
<binding name="listener" value="listener:submit2"/>
</component>
Home.java
public abstract class Home extends BasePage{
@InjectPage("Home")
public abstract Home getHome();
private String input1;
private String input2;
public String getInput1() {
return input1;
}
public void setInput1(String input1) {
this.input1 = input1;
}
public String getInput2() {
return input2;
}
public void setInput2(String input2) {
this.input2 = input2;
}
public IPage submit1(){
this.setInput2(this.getInput1()+this.getInput2());
return getHome();
}
public IPage submit2(){
this.setInput1(this.getInput1()+this.getInput2());
return getHome();
}
}
运行程序,对input1,input2,submit1,submit2操作如下:
1,在input1中输入1;input2中输入2,如图:

2,点击submit1,得到如下结果:

3,重复步骤1, 在input1中输入1;input2中输入2,然后点击submit2,得到如下结果:

------------------------------
上述,操作中input2根本没有接受任何参数,但是input1却是正常的,请问这个问题是什么原因造成?是否是bug.
是测试时候用的,忘记删掉了,不好意思
顺便说一下,为什么这里的代码那么丑陋,就不能把
原理vlinux讲过了
Tapestry把一切都看成是组件,自然TextField组件和Submit组件也就没有任何区别,他们都会被一视同仁,谁先定义谁就先被执行。
更具体一点,是(详细请参见文档和源代码):
submit被点击之后,执行form.rewind,page开始进入rewind流程(cycle.isRewound=true):
1、form中各个实现了IFormComponent的组件根据其在模版中定义的先后次序开始执行各自的rewindFormComponent(IMarkupWriter writer, IRequestCycle cycle)方法。
对于submit这样的带有监听事件的form组件,rewindFormComponent(writer, cycle)会调用其listener方法;
对于textfield这样的接受输入值的form组件,rewindFormComponent(writer, cycle)会将recycle中的request parameter值bind到textfield的value表达式。
2、最后执行form的listener事件方法。
因此对于你的这个测试来说,submit在模版中位于input之前,而要在submit的监听事件中得到input的值,是不可以的。
vlinux给出一个解决办法是把submit的事件处理放在form的listener中,目前来讲好像没有更好的办法。
环境:T4
Home.html
<html><body jwcid="@Body">
<table width="246" border="0" cellpadding="0" cellspacing="0" align="center">
<form jwcid="submitForm">
<tr><td width="219" height="16" valign="top">
input1<input type="text" name="textfield" jwcid="input1"/>
</td></tr>
<tr><td height="23" valign="top">
<input type="submit" name="Submit2" jwcid="submit1"/>
</td></tr>
<tr><td height="21" valign="top">
<input type="submit" name="Submit22" jwcid="submit2"/>
</td></tr>
<tr><td height="29" colspan="2" valign="top">
input2<input type="text" name="textfield22" jwcid="input2"/>
</td></tr>
</form>
</table>
</body></html>
Home.page
<component id="submitForm" type="Form"/>
<component id="input1" type="TextField">
<binding name="value" value="input1"/>
</component>
<component id="input2" type="TextField">
<binding name="value" value="input2"/>
</component>
<component id="submit1" type="Submit">
<binding name="listener" value="listener:submit1"/>
</component>
<component id="submit2" type="Submit">
<binding name="listener" value="listener:submit2"/>
</component>
Home.java
public abstract class Home extends BasePage{
@InjectPage("Home")
public abstract Home getHome();
private String input1;
private String input2;
public String getInput1() {
return input1;
}
public void setInput1(String input1) {
this.input1 = input1;
}
public String getInput2() {
return input2;
}
public void setInput2(String input2) {
this.input2 = input2;
}
public IPage submit1(){
this.setInput2(this.getInput1()+this.getInput2());
return getHome();
}
public IPage submit2(){
this.setInput1(this.getInput1()+this.getInput2());
return getHome();
}
}
运行程序,对input1,input2,submit1,submit2操作如下:
1,在input1中输入1;input2中输入2,如图:
2,点击submit1,得到如下结果:
3,重复步骤1, 在input1中输入1;input2中输入2,然后点击submit2,得到如下结果:
------------------------------
上述,操作中input2根本没有接受任何参数,但是input1却是正常的,请问这个问题是什么原因造成?是否是bug.
1 楼
vlinux
2006-10-14
Tapestry把一切都看成是组件,自然TextField组件和Submit组件也就没有任何区别,他们都会被一视同仁,谁先定义谁就先被执行。
你把input2放在submit2之后,那么input2将会在submit2执行完之后才能获取从表单传入来的值
你在input2和submit2中放一些mark就知道了
public void setInput2(String input2) {
this.input2 = input2;
System.out.println("我是setInput2(),我运行拉");
}
public IPage submit2(){
setInput1(getInput1() + getInput2());
System.out.println("我是submit2(),我运行拉");
return this;
}
如果按照
input1<input jwcid="input1"/><br>
<input type="submit" value="Submit1" jwcid="submit1"/><br>
<input type="submit" value="Submit2" jwcid="submit2"/><br>
input2<input jwcid="input2"/><br>
这样定义,那么我们可以得到的输出是:
我是submit2(),我运行拉
我是setInput2(),我运行拉
很明显,赋值发生在调用之后。所以会有null出现
不知道我解释得对不对哈~~
你把input2放在submit2之后,那么input2将会在submit2执行完之后才能获取从表单传入来的值
你在input2和submit2中放一些mark就知道了
public void setInput2(String input2) {
this.input2 = input2;
System.out.println("我是setInput2(),我运行拉");
}
public IPage submit2(){
setInput1(getInput1() + getInput2());
System.out.println("我是submit2(),我运行拉");
return this;
}
如果按照
input1<input jwcid="input1"/><br>
<input type="submit" value="Submit1" jwcid="submit1"/><br>
<input type="submit" value="Submit2" jwcid="submit2"/><br>
input2<input jwcid="input2"/><br>
这样定义,那么我们可以得到的输出是:
我是submit2(),我运行拉
我是setInput2(),我运行拉
很明显,赋值发生在调用之后。所以会有null出现
不知道我解释得对不对哈~~
2 楼
yi527
2006-10-14
to vlinux:
很明显,赋值发生在调用之后。所以会有null出现
submit仅仅是listener,页面的控件无论放在何处,只要处于form里面,在接受调用的时候都应该产生作用。
在我给的例子中,两个text是故意分开来放置的,如果按照你的说法,那么submit永远必须在页面的低端?
现在问题的关键是,调用submit时,input2没有正常的工作。这到底html页面设置问题,还是程序的问题?
BTW:我另外测过,将input1,input2调置submit控件之前(html中),一切ok.
很明显,赋值发生在调用之后。所以会有null出现
submit仅仅是listener,页面的控件无论放在何处,只要处于form里面,在接受调用的时候都应该产生作用。
在我给的例子中,两个text是故意分开来放置的,如果按照你的说法,那么submit永远必须在页面的低端?
现在问题的关键是,调用submit时,input2没有正常的工作。这到底html页面设置问题,还是程序的问题?
BTW:我另外测过,将input1,input2调置submit控件之前(html中),一切ok.
3 楼
vlinux
2006-10-15
我认为你的错误是因为代码的原因造成的。
“submit仅仅是listener,页面的控件无论放在何处,只要处于form里面,在接受调用的时候都应该产生作用。”
这句是没有错,但是仅仅用在
这里
你定义的是Submit组件,但是并没有告诉Tapestry你的Form的listener是谁。
所以我们可以这样写代码
Home.html
Home.java
这样就可以了。
综上所述,我个人认为你的错误是代码造成的,欢迎拍砖~呵呵
“submit仅仅是listener,页面的控件无论放在何处,只要处于form里面,在接受调用的时候都应该产生作用。”
这句是没有错,但是仅仅用在
<form jwcid="@Form" listener="listener:emptySubmit">
这里
你定义的是Submit组件,但是并没有告诉Tapestry你的Form的listener是谁。
所以我们可以这样写代码
Home.html
<html> <body> <form jwcid="@Form" listener="listener:emptySubmit"> input1<input jwcid="@TextField" value="ognl:input1"/><br> <input type="submit" jwcid="@Submit" value="submit1" action="listener:submit1"/><br> <input type="submit" jwcid="@Submit" value="submit2" action="listener:submit2"/><br> input2<input jwcid="@TextField" value="ognl:input2"/><br> </form> </body> </html>
Home.java
public abstract class Home extends BasePage{ public abstract String getInput1(); public abstract String getInput2(); public abstract void setInput1( String input1 ); public abstract void setInput2( String input2 ); public abstract String getInput3(); public void submit1(){ setInput1( getInput1() + getInput2() ); } public void submit2(){ setInput2( getInput2() + getInput1() ); } public IPage emptySubmit(){ return this; } }
这样就可以了。
综上所述,我个人认为你的错误是代码造成的,欢迎拍砖~呵呵
4 楼
vlinux
2006-10-15
public abstract String getInput3();
是测试时候用的,忘记删掉了,不好意思
顺便说一下,为什么这里的代码那么丑陋,就不能把
弄得好看点么
5 楼
yi527
2006-10-17
to vlinux:
thank you!
代码我测了,一切ok!
但还是有一个问题,难道一点不能在submit1或submit2中实现调用吗?
请教原理。^_^
thank you!
代码我测了,一切ok!
但还是有一个问题,难道一点不能在submit1或submit2中实现调用吗?
请教原理。^_^
6 楼
sorphi
2006-10-17
yi527 写道
to vlinux:
thank you!
代码我测了,一切ok!
但还是有一个问题,难道一点不能在submit1或submit2中实现调用吗?
请教原理。^_^
thank you!
代码我测了,一切ok!
但还是有一个问题,难道一点不能在submit1或submit2中实现调用吗?
请教原理。^_^
原理vlinux讲过了
vlinux 写道
Tapestry把一切都看成是组件,自然TextField组件和Submit组件也就没有任何区别,他们都会被一视同仁,谁先定义谁就先被执行。
更具体一点,是(详细请参见文档和源代码):
submit被点击之后,执行form.rewind,page开始进入rewind流程(cycle.isRewound=true):
1、form中各个实现了IFormComponent的组件根据其在模版中定义的先后次序开始执行各自的rewindFormComponent(IMarkupWriter writer, IRequestCycle cycle)方法。
对于submit这样的带有监听事件的form组件,rewindFormComponent(writer, cycle)会调用其listener方法;
对于textfield这样的接受输入值的form组件,rewindFormComponent(writer, cycle)会将recycle中的request parameter值bind到textfield的value表达式。
2、最后执行form的listener事件方法。
因此对于你的这个测试来说,submit在模版中位于input之前,而要在submit的监听事件中得到input的值,是不可以的。
vlinux给出一个解决办法是把submit的事件处理放在form的listener中,目前来讲好像没有更好的办法。
7 楼
yi527
2006-10-18
谢谢vlinux和sorphi。
8 楼
baizhan
2006-10-18
受教了...最近刚好在学TAPESTRY...没有注意到这个问题..呵呵..
9 楼
fxsc
2006-10-18
使用submit的action属性代替lisener
10 楼
yi527
2006-10-19
to vlinux和sorphi:
根据fxsc的建议,我改了一下测试的例子:
测试ok,可以在submit中直接调用。没有必要通过form的listener来执行。
thank you all.
根据fxsc的建议,我改了一下测试的例子:
<component id="submitForm" type="Form"/> <component id="input1" type="TextField"> <binding name="value" value="input1"/> </component> <component id="input2" type="TextField"> <binding name="value" value="input2"/> </component> <component id="submit1" type="Submit"> <binding name="action" value="listener:submit1"/> </component> <component id="submit2" type="Submit"> <binding name="action" value="listener:submit2"/> </component>
@InjectPage("Home") public abstract Home getHome(); public IPage submit1(){ getHome().setInput2(getInput1() + getInput2()); return getHome(); } public IPage submit2(){ getHome().setInput1(getInput1() + getInput2()); return getHome(); }
测试ok,可以在submit中直接调用。没有必要通过form的listener来执行。
thank you all.