Monday 20 February 2012

SwingBuilder Series: Binding (I)


Binding is a really powerful feature. You can wire model properties with UI properties and viceversa. Before writing my own examples I recommend the following links:
Here we have a simple login form. We want the user to insert a username and a password before let him click the validation button.


We have different ways to do that. The first way we're wiring UI events and properties. There's no back model to register UI values.
vbox{
label("Username")
textField(id:'username')
label("Password")
passwordField(id:'password')
button(
id:'submit',
text:'Enter username & password',
enabled: bind{username.text && password.text},
actionPerformed:{submit.text = 'Validation OK'}
)
}
This approach is really easy, you can bind the enabled property from the button to the result of evaluating the username text and the password text. Although it is a really easy way to accomplish the job, later we may want to get the value of each field, and I don't want to do it one by one. There must be a way of mapping UI fields' values with the underlying model.

But I want to store the form values in an instance of the object User:
import groovy.beans.*

@Bindable
class User{
String username
String password
Boolean valid
}

def user = new User()

Notice I've annotated my User class with Bindable. This will trigger an event each time user's properties change.

The UI:
vbox{
label("Username")
textField(id:'username')
label("Password")
passwordField(id:'password')
bean(user,username:bind{username.text})
bean(user,password: bind{password.text})
bean(user,valid:bind{password.text && username.text})
button(
id:'submit',
text:'Enter username & password',
enabled: bind{user.valid},
actionPerformed:{
submit.text = "user:${user.username}, password:${user.password}"
}
)
}
Notice each bean node wires one of the user's properties with one of the UI's fields values, or event with a formula (using both of them).

Finally the button's enabled property is bind with the "valid" property from the user's instance.

Using the bind node this way will give you access directly to the user's properties instead of getting each UI field value and then copying that value to the bean property.









No comments:

Post a Comment