Convert Grails 2 View to Use Knockout JS
When the basic functionality of a web application has been developed, it’s time to add interactive features. Filtering a list of users is one task that is better done on the client side than on the server, to provide faster response. First, the Groovy variables need to be converted to JSON to be rendered in the view.
[cc lang=”groovy”]
def newMessage = {
def user = User.get(session.user.id)
def account = CustomerAccount.get(session.account.id)
[messageInstance: new Message(params), usersForAllDepartments: userService.getUsersForAllDepartments(user)]
}
[/cc]
[cc lang=”groovy”]
def newMessage = {
…
[messageInstance: new Message(params), usersForAllDepartments: userService.getUsersForAllDepartments(user).collect{[id: it.id, name: it.name]} as JSON]
}
[/cc]
Next, change the looping constructs and logic to use Knockout:
[cc lang=”html”]
[/cc]
[cc lang=”html”]
[/cc]
Simply replace the tags with Knockout’s containerless control flow tags and bind to data values. Knockout is more terse, as the user for each iteration doesn’t need to be referenced. Render the JSON list of users on the page before the main part of the JavaScript code, which I like to keep in a separate deferred (CoffeeScript) file.
[cc lang=”html”]
[/cc]
Finally, apply Knockout’s bindings to it with the user list loaded.
[cc lang=”javascript”]
function Recipient(data) {
this.name = ko.observable(data.name);
this.selected = ko.observable(false);
this.id = data.id;
}
function MessageViewModel() {
var self = this;
self.recipients = ko.observableArray([]);
// Load initial state
var mappedRecipients = $.map(usersForAllDepartments, function(item) { return new Recipient(item) });
self.recipients(mappedRecipients);
}
ko.applyBindings(new MessageViewModel());
[/cc]
The rendered HTML looks exactly the same as before (except for data-bind).
[cc lang=”html”]
[/cc]