Models are very simple in nature. Their responsibility is to hold data that can be used by both Controller and View to communicate with each other. In other words, Models are not equivalent to domain classes.

Models can be observable by means of the @Bindable AST Transformation. This actually simplifies setting up bindings so that changes in the UI can automatically be sent to model properties and vice versa.

@Bindable will inject a java.beans.PropertyChangeSupport field and all methods required to make the model an observable class. It will also make sure that a PropertyChangeEvent is fired for each observable property whenever said property changes value.

The following is a list of all methods added by @Bindable

The following is a list of all methods added by @Vetoable

Another annotation, @Listener, helps you register PropertyChangeListeners without so much effort. The following code

import griffon.transform.PropertyListener
import groovy.beans.Bindable

@PropertyListener(snoopAll) class MyModel { def controller @Bindable String name

@Bindable @PropertyListener({controller.someAction(it)}) String lastname

def snoopAll = { evt -> … } }

is equivalent to this one

import groovy.beans.Bindable
import java.beans.PropertyChangeListener

class MyModel { def controller @Bindable String name @Bindable String lastname

def snoopAll = { evt -> … }

MyModel() { addPropertyChangeListener(snoopAll as PropertyChangeListener) addPropertyChangeListener('lastname', { controller.someAction(it) } as PropertyChangeListener) } }

@PropertyListener accepts the following values