More code is more work
Large projects mean large compile times
Declarative good, boilerplate bad
Declarative client-side features
Dependency Injection
A simple bean
public class MySimpleServiceImpl implements MySimpleService {
@Override
public void doTheThing() {
// ...
}
}
public class ServiceUser {
@Inject
MySimpleServiceImpl service;
}
A bean with a dependency
public class ServiceUser {
@Inject
MySimpleService service;
}
public class ServiceUser {
final MySimpleService service;
@Inject
public ServiceUser(MySimpleService service) {
this.service = service;
}
}
public class ServiceUser {
MySimpleService service;
@Inject
public void setService(MySimpleService service) {
this.service = service;
}
}
Constructor and setter injection
Supports more CDI features
Declarative templating
How does it work?
@Templated
public class MyForm extends Composite {
@Inject
@DataField
TextBox text;
@DataField
Button submit = new Button();
}
<div>
<input data-field="text" type="text" />
<input data-field="submit" type="button" />
</div>
Declaring event handlers
@Templated
public class MyForm extends Composite {
@Inject
@DataField
TextBox text;
@DataField
Button submit = new Button();
@EventHandler("submit")
private void onClick(ClickEvent event) {
// Do the thing...
}
}
Template inception
@Templated
public class MyFormView extends Composite {
@Inject
@DataField
MyForm form;
}
<div>
<div data-field="form">
<!--
The contents of this div will be replaced
at runtime with the html fragment for MyForm
-->
<span>I am content that won't be rendered!</span>
</div>
</div>
<div>
<div data-field="form">
<input data-field="text" type="text" />
<input data-field="submit" type="button" />
</div>
</div>
Designer templates
@Templated("DesignerTemplate.html#contact")
public class ContactView extends Composite {
}
<!DOCTYPE html>
<html>
<head>
<title>Designer Template</title>
</head>
<body>
<navbar>
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#contact">Contact</a></li>
</navbar>
<section id="home">
<h1>Home</h1>
<p>This is the home section.</p>
</section>
<section id="contact">
<h1>Contact</h1>
<p>This is the contact section.</p>
</section>
</body>
</html>
<section id="contact">
<h1>Contact</h1>
<p>This is the contact section.</p>
</section>
What is data-binding?
How does it work?
@Bindable
public class User {
private String username;
private Date dateOfBirth;
public void setUsername(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
}
@Templated
public class NewUserForm extends Composite {
@Inject @AutoBound
DataBinder<User> binder;
@Inject
@Bound
@DataField
TextBox username;
@Inject
@Bound(property="dateOfBirth")
@DataField
DateBox dob;
@Inject
@DataField
Button submit;
@EventHandler("submit")
private void onClick(ClickEvent event) {
User newUser = binder.getModel();
// These will be true
assert newUser.getUsername().equals(username.getValue());
assert newUser.getDateOfBirth().equals(dob.getValue());
// ...
}
}
User user = binder.getModel();
// This updates the value in the TextBox widget
user.setUsername("Max");
// So this must be true
assert username.getValue().equals("Max");
Going the other direction
Binding a list of values
@Templated
public class UserView extends Composite implements HasModel<User> {
// ...
@Override
public void setModel(User model) {
binder.setModel(model);
}
@Override
public User getModel() {
return binder.getModel();
}
}
@Inject
ListWidget<User, UserView> userList;
List<User> models = userList.getValue();
// All of these will affect the list of displayed widgets
models.add(new User());
models.get(0).setUsername("John");
models.remove(0);
Demo time
How does it work?
Goals
JsInterop
@JsType
package org.errai.example;
@JsType
public class User {
private String username;
public void getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
var user = new org.errai.example.User();
user.setUsername("Max");
// Returns "Max"
user.getUsername();
How Errai uses JsInterop
Sharing an implementation
public interface MySimpleService {
void doTheThing();
}
public class MySimpleServiceImpl implements MySimpleService {
@Override
public void doTheThing() {
// ...
}
}
public static native MySimpleService createService()/*-{
return new producer.MySimpleServiceImpl();
}-*/;
How do I share?
@JsType
public interface MySimpleService {
void doTheThing();
}
@JsType
public class MySimpleServiceImpl implements MySimpleService {
@Override
public void doTheThing() {
// ...
}
}
Consumer usage
public class ConsumingBean {
@Inject
MySimpleService service;
}
Producer usage
How could I use this?
What can Errai do for you?
Thanks for listening!