0.4.1

Relationships

Flutter Data has a powerful relationship mapping system.

  • HasMany<T> for to-many relationships
  • BelongsTo<T> for to-one relationships

As an example, a User has many Todos:

@JsonSerializable()
@DataRepository([StandardJSONAdapter, JSONPlaceholderAdapter])
class User extends DataSupport<User> {
  @override
  final int id;
  final String name;
  final HasMany<Todo> todos;

  User({this.id, this.name, this.todos});
}

and a Todo belongs to a User:

@JsonSerializable()
@DataRepository([StandardJSONAdapter, JSONPlaceholderAdapter])
class Todo extends DataSupport<Todo> {
  @override
  final int id;
  final String title;
  final bool completed;
  final BelongsTo<User> user;

  Todo({this.id, this.title, this.completed = false, this.user});
}

So long as:

  • Models have their respective HasMany/BelongsTo relationships DEFINED (always as final!)
  • The API responds correctly with relationship data (i.e. a User with a collection of Todo models – or just IDs if models were already loaded)

we can expect the following to work:

User user = await repository.findOne(1, params: {'_embed': 'todos'});

Todo todo = user.todos.first;

print(todo.title); // write Flutter Data docs

print(todo.user.value.name); // Frank

// or

final house = House(address: "Sakharova Prospekt, 19");
final family = Family(surname: 'Kamchatka', house: BelongsTo(house));

print(family.house.value.families.first.surname);  // Kamchatka

There’s more in the Dart example app!

Relationship extensions

A User with Todos could be created like this:

final t1 = Todo(title: 'do 1');
final t2 = Todo(title: 'do 2');

final user = User(name: 'Frank', todos: HasMany({t1, t2}));

// or

final user = User(name: 'Frank', todos: {t1, t2}.asHasMany);

or a Todo with User:

final user = User(name: 'Frank');

final todo = Todo(title: 'do 1', user: BelongsTo(user));

// or

final todo = Todo(title: 'do 1', user: user.asBelongsTo);

Defaults

If you don’t want to keep creating Todos with unknown User like:

final todo = Todo(title: 'do 1', user: BelongsTo());

Then it is strongly encouraged to provide defaults like:

@JsonSerializable()
@DataRepository([StandardJSONAdapter, JSONPlaceholderAdapter])
class Todo extends DataSupport<Todo> {
  @override
  final int id;
  final String title;
  final bool completed;
  final BelongsTo<User> user;

  Todo({this.id, this.title, this.completed = false, BelongsTo<User> user}) :
    user = user ?? BelongsTo();
}