Anda di halaman 1dari 19

List editor

herebebeasties.com

Alastair Maw

London Wicket User Group


Hosted by Google UK 6 February 2008

Lists
Add Remove Sort

What things?

Anything.

Type of data
String JPEG le ACME widget

Component
Label Image AcmeWidgetPanel

ListView
<div wicket:id="item"> <span wicket:id="name"> Name goes here </span> </div>

List<String> employeeNames = getEmployeeNames(); add(new ListView("item", employeeNames) { public void populateItem(ListItem item) { item.add(new Label("name", item.getModel())); } });

ListEditors ListView
<div wicket:id="container"> <div wicket:id="item"> <div class="handle">Drag me</div> <a wicket:id="deleteLink">Delete</a> <div wicket:id="component">Item goes here</div> </div> </div> container.add(new ListView("item", listOfStuff) { public void populateItem(ListItem item) { item.add(new Link("deleteLink") { public void onClick() { /* ... */ } }); IModel model = item.getModel(); item.add(getItemComponent("component", model)); } });

Script.aculo.us comes with a JS Sortable class:


<ul id="container"> <li id="item_0"> first </li> <li id="item_1"> second </li> <li id="item_2"> third </li> </div> Sortable.create($('container'), { onUpdate: function(element) { var data = Sortable.serialize(element); // TODO: Send data back to server. } });

Sortable.serialize() output looks like this:


container[]=1&container[]=2&container[]=0

Within our Java-based Wicket code we can go:


getRequest().getParameters("container[]");

Sending the data back


function createSortable(element, callbackUrl) { Sortable.destroy(element); Sortable.create(element, { handle: 'handle', dropOnEmpty: true, constraint: false, tag: 'div', onUpdate: function(element) { wicketAjaxGet(callbackUrl + "&" + Sortable.serialize(element)); } }); }

What about the Java?


Wicket uses Behaviors to implement AJAX. Extend AbstractDefaultAjaxBehavior and implement its respond() method. The result of getCallbackUrl() is passed into the JavaScript so we can call it. Use wicketAjaxGet() to perform the AJAX request.

The behavior
protected void respond(AjaxRequestTarget target) { // Get the new order from the GET param array. String[] newOrder = getRequest().getParameters( container.getMarkupId() + "[]"); // Reorder the backing java.util.List according. reorderList(newOrder); // Repaint the list and recreate the JS Sortable. target.addComponent(listEditorContainer); target.appendJavascript("createSortable('" + container.getMarkupId() + "', '" + getCallbackUrl() + "');"); }

The behavior
We need to run the createSortable() JavaScript when we rst render the page. Behaviors have a method renderHead() which lets you add JS, CSS, etc. to a page.

The behavior
public void renderHead(IHeaderResponse response) { super.renderHead(response); response.renderOnDomReadyJavascript( "createSortable('" + container.getMarkupId() + "', '" + getCallbackUrl() + "');" ); }

Wrinkles
We want handles for drag and drop, so list items can be clickable. This is done with an extra handle param in the options to the JS Sortable.create() call. We need to add a bunch of CSS classes to the elements so we can style the drag handles, etc.

Whats it look like?

What do we have?
~10 lines of HTML. ~10 lines of JavaScript. ~80 lines of Java. A smidgin of CSS. A one-line properties le if you want to internationalize the Add new link.

But I can do that with the xyzzy framework just as easily!

Questions?

More talks and source code are available at: http://londonwicket.org/ For more information about Wicket: http://wicket.apache.org

Anda mungkin juga menyukai