Développer avec Grails 3 et le profil Angular

Depuis sa version 3.2.1, le framework web Grails propose le profil de développement angular2, permettant de développer un projet consistant en une partie serveur, basée sur Grails, et une partie cliente reposant sur une application web Angular 2.

Un tel projet s'initialise avec la commande Grails create-app ainsi :

grails create-app <my-app> --profile=angular2

A titre d'exemple, j'ai mis en ligne le projet odelia-gina-angular2, créé avec le profil angular2, et permettant de gérer une simple liste de todos.

Partie serveur

Pour rester simple, l'application Grails définit un service REST au travers du ressource métier prenant la forme d'une classe annotée avec @Resource ; cette classe métier représente un todo, tandis que le framework va permettre la persistance des entités de ce type :

1
2
3
4
5
@Resource(readOnly = false, formats = ['json'])
class Todo {
    String title
    Boolean complete
}

De plus, le fait d'utiliser l'annotation @Resource offre d'emblée une API REST pour la gestion de la ressource todo.

Notez que dans le fichier de configuration application.yml de l'application Grails, CORS est activé.
Pour notre application web Angular, cela va permettre l'accès au service REST situé dans un autre domaine.

Partie cliente

Angular 2 étant un framework orienté composant, c'est un composant, le composant TodosComponent, déclaré dans l'application cliente, qui gère les todos typés par la classe TypeScript Todo :

1
2
3
4
5
export class Todo {
    id: number;
    title: string = '';
    complete: boolean = false;
}

Le composant TodosComponent :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Component({
  selector: 'app-todos',
  templateUrl: './todos.component.html',
  styleUrls: ['./todos.component.css'],
  providers: [TodosService]
})
export class TodosComponent implements OnInit {
  newTodo: Todo = new Todo();
  todos: Todo[] = [];

  constructor(private todosService: TodosService) { }

  ngOnInit() {
    this.todosService.getTodos()
      .subscribe(
        todos => this.todos = todos,
        error => console.log('Error: ' + error)
      );
  }
  // ...
}

La méthode ngOnInit du composant obtient la liste des todos grâce au service Angular injecté de type TodosService et un appel à sa méthode getTodos() qui renvoit un Observable :

1
2
3
4
5
6
7
8
9
10
11
12
13
export class TodosService {

  baseUrl: String = 'http://localhost:8080';

  constructor(private http: Http) { }

  getTodos() {
    return this.http.get(`${this.baseUrl}/todo`)
      .map(response => response.json());        
  }

  // ...
}

Ici, le service Angular Http permet d'obtenir la liste des todos au format JSON, en émettant une requête HTTP de type GET sur l'URL http://localhost:8080/toto ; cette URL correspond bien sûr au service REST exposé par l'application Grails.

L'application web Angular permet également d'ajouter ou de supprimer des todos, ou encore d'en marquer comme terminés.