# Reactivity System
TIP
Vue.js reactivity system is based on ES5 getter/setters which have limitations.
In the future, Vue will use ES6 proxies for it's reactivity system, and the limitations below will disappear 🎉. We will however leave the option to keep the old reactivity system on a given project for IE 11 compatibility.
# Objects Observation
When you assign an Object to a @Data
of a Component, all it's properties must already be set in the JS world to be observed.
This means that they must have a value set, even if null.
In this case the text
property WON'T be observed:
public class Todo {
private String text;
public Todo() {}
public void setText(String text) { this.text = text; }
}
@Component
public class MyComponent implements IsVueComponent, HasCreated {
@Data Todo todo;
@Override
public void created() {
todo = new Todo();
todo.setText("Bob"); // Won't update the Vue :(
}
}
But in these cases it will WILL:
// Any of those
public class Todo {
private String text = null;
...
}
public class Todo {
private String text;
public Todo() {
this.text = null;
}
...
}
public class Todo {
private String text = "Default Value";
...
}
public class Todo {
private String text;
public Todo() {
this.text = "Default Value";
}
...
}
public class Todo {
private String text;
public Todo(String defaultText) {
this.text = defaultText;
}
...
}
// The text property will be observable in your Component
@Component
public class MyComponent implements IsVueComponent, HasCreated {
@Data Todo todo;
@Override
public void created() {
todo = new Todo();
todo.setText("Bob"); // Will update the Vue!
}
}
If you don't have the control over the Java class, you can also set a value before attaching your object to your Component data model.
// This class comes from some library, I can't change it! How do I make text reactive?
public class Todo {
private String text;
public Todo() {}
public void setText(String text) { this.text = text; }
}
@Component
public class MyComponent implements IsVueComponent, HasCreated {
@Data todo;
@Override
public void created() {
Todo myTodo = new Todo(); // We store in a local variable
myTodo.setText("Bob"); // We set the value, this define the property
this.todo = myTodo; // We attach myTodo, it starts being observed, Bob displays in the Vue!
todo.setText("Mickael"); // Will update the Vue to Mickael!
}
}
# Java Collections Observation
Due to JavaScript getter/setter limitations Vue.js cannot observe some changes on JavaScript Arrays.
All Java Collections have a JavaScript implementation provided by GWT. In some cases, these implementations use JavaScript Arrays to store their data. This mean that some Java Collection cannot be automatically observed by Vue.js.
Luckily, Vue GWT goes around this limitation for you by wrapping java Collections mutation methods. When calling any of these methods, Vue GWT will warn Vue.js observer to trigger a view update.
The wrapped methods are:
- For
List
:add
,addAll
,clear
,remove
,removeAll
,retainAll
,set
- For
Set
:add
,addAll
,clear
,remove
,removeAll
,retainAll
- For
Map
:put
,putAll
,putIfAbsent
,replace
,clear
,remove
For this to work the name of these methods must not change when your code is optimized by GWT.
To tell GWT that you want this, you must always:
- Use either
List
,Set
orMap
for your property type, never the concrete type. - Always use the
@JsProperty
annotation on top of your collection fields, on Class that will be in a@Data
.
Here is a valid example of a UsersRepository
containing a collection of Users:
class UsersRepository {
@JsProperty
List<User> myUsers;
}
TIP
Vue GWT will check for you all your @Data
fields (recursively) and all your @Prop
fields (non-recursively) at compile time to make sure they respect the rules on collection fields.
If they don't Vue GWT will throw an explicit compile time exception.
If you wish to disable this error on a specific field you can add the annotation @SuppressWarnings("vue-gwt-collections")
to it.