joist-web pages are objects that implement the Page interface.
Pages are responsible for initializing controls to render the page and handle any user interaction on form submissions.
joist-web maps class names from URLs simply:
/dir/file.htm to com.yourmap.basepackage.dir.FilePageAlthough you can override this mapping in the PageResolver class.
This is the code-behind Page class for foo.htm, a data-entry page for Foo objects:
@Bindable
public class FooPage extends AbstractProjectPage {
// When hitting foo.htm?foo=1, Foo with id=1 is put into this field
public Foo foo;
public Form form = new Form("form");
@Override
public void onInitt() {
if (this.foo == null) {
// They hit the "new" button instead of the "edit" button
this.foo = new Foo();
}
// Define the form using the bindgen-generated bindings
FooPageBinding b = new FooPageBinding(this);
this.form.add(new TextArea(b.foo().name()));
this.form.add(new TextArea(b.foo().description()));
this.form.add(new SubmitButton(b.save()));
}
// In AbstractProjectPage, DomainObjects are not allowed to be set into any public field
// unless this method explicitly allows them--prevents users from screwing with URLs
@Override
public boolean isAllowedViaUrl(DomainObject instance) {
return instance instanceof Foo && ((Foo) instance).getUser().equals(this.currentUser.get());
}
// Called when the user hit's submit
public void save() {
if (this.commit()) {
this.messages.addInfo("Successfully saved {}", this.foo);
redirect(EntriesPage.class);
}
}
}
And now the foo.htm, which is a Velocity template:
$form
Across lots of pages, the succinctness of the foo.htm page and the type-safety of the bindgen-based Form definition should be a boon to productivity.