public void onInit() { super.onInit(); form.add(nameField); form.add(checkbox); // NB: when using form.submit() the submit button cannot be // called 'submit'. If it is, the browser is likely to throw a JS exception. checkbox.setAttribute("onclick", "form.submit()"); ... // NB: Bind the submit button. If it wasn't clicked it means the Form was submitted // using JavaScript and we don't want to validate yet ClickUtils.bind(submit); // If submit was not clicked, don't validate if(form.isFormSubmission() && !submit.isClicked()) { form.setValidate(false); } submit.setActionListener(new ActionListener() { public boolean onAction(Control source) { // We can safely call isValid from within the submit action handler // since validation is always active if the submit button was clicked if (form.isValid()) { addModel("msg", "Form is valid after validation"); } return true; } }); }
public class MyPage extends BorderPage { protected static final String HTML_IMPORT = "<link rel=\"stylesheet\" type=\"text/css\" src=\"{0}/js/mylib.css\"/>\n" + "<script type=\"text/javascript\" src=\"{0}/js/mylib.js\"></script>\n" + "<script type=\"text/javascript\">alert('Hello World!');</script>\n"; public String getHtmlImports() { String[] args = { getContext().getRequest().getContextPath() }; return MessageFormat.format(HTML_IMPORTS, args); } }After:
public class MyPage extends BorderPage { public List getHeadElements() { // Cater for stateful pages. If you don't use stateful pages you don't need this check if (headElements == null) { headElements = super.getHeadElements(); headElements.add(new CssImport("/js/mylib.css")); headElements.add(new JsImport("/js/mylib.js")); JsScript script = new JsScript(); script.setContent("alert('Hello World!');"); headElements.add(script); } return headElements; } }
import org.apache.click.extras.control.DateField; ... DateField dateField = new DateField("date");with this:
import net.sf.click.extras.control.CalendarField; ... DateField dateField = new CalendarField("date");CalendarField subclasses DateField so the above snippet is valid. See the Click Calendar project for more details.
table.add(new Column("name")).setSortable(true); form.add(new TextField("firstname")).setValue("Bob");If you created a custom Form, FieldSet or Table and overrode the add or addColumn method, you will be forced to return the methods argument. For example if you had:
public class MyTable { public void addColumn(Column column) { ... } }you will need to update as follows:
public class MyTable { public Column addColumn(Column column) { ... // You must return the column return column; } }
public class HtmlTable extends AbstractControl { ... public String toString() { int estimatedControlSize = 1000; HtmlStringBuffer buffer = new HtmlStringBuffer(estimatedControlSize); // Rendering Start buffer.elementStart("table"); appendAttributes(buffer); buffer.elementClose(); renderRows(buffer); buffer.closeElement("table"); // Rendering End return buffer.toString(); } }to this:
public class HtmlTable extends AbstractControl { ... public void render(HtmlStringBuffer buffer) { // Rendering Start buffer.elementStart("table"); appendAttributes(buffer); buffer.elementClose(); renderRows(buffer); buffer.closeElement("table"); // Rendering End } public String toString() { int estimatedControlSize = 1000; HtmlStringBuffer buffer = new HtmlStringBuffer(estimatedControlSize); render(buffer); return buffer.toString(); } }Note, the code between the commented section, was moved from toString to the render method. Also note that invoking a Control's toString() method still outputs the same HTML representation, as toString() delegates to the render method. Please note a common problem when overriding render in custom components, is invoking super.toString() in order to render the Control's default markup:
public class CustomField extends Field {
...
public void render(HtmlStringBuffer buffer) {
String field = super.toString(); // BEWARE this line will cause StackOverflowError
...
}
public String toString() {
HtmlStringBuffer buffer = new HtmlStringBuffer();
render(buffer);
return buffer.toString();
}
}
The highlighted line above will cause a StackOverflowError, meaning an infinite
loop was encountered. The reason for the error will become obvious when
tracing the sequence of calls:
public class CustomField extends Field {
...
public void render(HtmlStringBuffer buffer) {
super.render(buffer); // NOTE StackOverflowError won't occur
...
}
public String toString() {
HtmlStringBuffer buffer = new HtmlStringBuffer();
render(buffer);
return buffer.toString();
}
}
<click-app charset="UTF-8"> <pages package="org.apache.click.examples.page"/> <log-service classname="org.apache.click.extras.service.JdkLogService"/> </click-app>While it is generally not recommended to use the Click LogService in your application code, you can retrieve it using the ClickUtils method getLogService().