问题
I have been trying to create a custom textfield in tapestry which will render some javascript when it gains focus. But I have been having trouble trying to find an example of this.
Here is some of the code i have started off with:
package asc.components;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.Field;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.ComponentDefaultProvider;
public class DahserTextField implements Field {
@Parameter (defaultPrefix = "literal")
private String label;
@Inject
private ComponentResources resources;
@Inject
private ComponentDefaultProvider defaultProvider;
@Parameter
private boolean disabled;
@Parameter
private boolean required;
String defaultLabel(){
return defaultProvider.defaultLabel(resources);
}
public String getControlName() {
return null;
}
public String getLabel() {
return label;
}
public boolean isDisabled() {
return disabled;
}
public boolean isRequired() {
return required;
}
public String getClientId() {
return resources.getId();
}
}
I have been unsure on what to do next. I do not know what to put into the .tml file. I would be grateful if anyone could help or point me in the right direction.
回答1:
There is no need to replicate any of TextField
's functionality in your own component, instead you should create a component mixin. Mixins are designed to add behaviour to existing components.
From the Tapestry 5 docs:
Tapestry 5 includes a radical feature, component mixins. Component mixins are a tricky concept; it basically allows a true component to be mixed together with special limited components called mixins. The component plus its mixins are represented as just a single tag in the component template, but all the behavior of all the elements.
You would use the mixin like this:
<input type="text" t:type="TextField" t:mixins="MyMixin" t:someParam="foo" />
A mixin stub:
@IncludeJavaScriptLibrary("MyMixin.js")
public class MyMixin {
/**
* Some string param.
*/
@Parameter(required = true, defaultPrefix = BindingConstants.LITERAL)
private String someParam;
@Environmental
private RenderSupport renderSupport;
@InjectContainer
private AbstractTextField field;
@AfterRender
void addScript() {
this.renderSupport.addScript("new MyJavascriptClass('%s', '%s');",
this.field.getClientId(), this.someParam);
}
}
Note the @InjectContainer
annotation, which injects the containing TextField into your Mixin. In this case, we want the TextField's clientId.
Also note the @IncludeJavaScriptLibrary("MyMixin.js")
annotation, which includes the required Javascript file.
The Javascript could look like this:
MyJavascriptClass = Class.create({
initialize: function(textField, someParam)
{
this.textField = $(textField);
this.someParam = someParam;
this.textField.observe('focus', this.onFocus.bindAsEventListener(this));
},
onFocus: function(event)
{
//do something
}
}
The key difference to your approach is that this involves defining your own JS class and using Tapestry's built-in facilities to load and initialize the JS. The use of mixins is also relatively light-weight and elegant in comparison to creating your own components.
回答2:
The .tml
<t:textfield onfocus="somethingCool()" />
The Java should probably extent TextField? It will need to import a new stylesheet too probably.
-- Pages are actually components, so you would build a component just like you would have any other page. You can embed any other component into them. I hope this is a good starting point for you.
来源:https://stackoverflow.com/questions/2801879/how-do-i-create-a-custom-text-field-in-tapestry5-that-renders-some-javascript-on