Play!> framework How-To : binding @ManyToMany to views (without CRUD) and differents UI

This is a little How-To for binding @ManyToMany relationship in Play!> views. The model for this very simple : a Domain model , and a User model. Users can belong to many domains and domains can have many models.

So, the Models are simple :

public class Domain extends Model {
	public String name;

	public String toString() {
		return name;
public class User extends Model {
    public String firstname;
    public String lastname;
	public List<Domain> domains = new ArrayList<Domain>();
    public String toString() {
    	return firstname + " " + lastname;

The relationship will be handle by the User view : the deafult component to handle this is the <select> form tag. So here is the basic code to make the binding.

    #{form, id:'userCreationForm', enctype:'multipart/form-data'}
    	<input name='' id='id-${user?.id}' type='hidden' value="${user?.id}"/>
		#{input for:'user.firstname', id:'firstname-${}' /}
		#{input for:'user.lastname', id:'lastname-${}' /}

	    <select id="user_domains" name="" value="" size="1" id="select" multiple>
        #{list domains, as:'domain'} 
  			<option value="${}" ${ ? 'selected' : ''} >${}</option>
		<input type="submit" value="Save">
	#{/form }

This will reproduce the same UI as in CRUDSs views. Note this two importants things :

  • the name of the select tag is :
  • to bind selected domains in the options, use the ternary operator and the contains method : ${ ? ‘selected’ : ”}

Changing the UI

I don’t really like this UI choice. As in the Yabe blog demo, we can change the UI of this view : we will user the same design as on the demo. We will use the same styles and javascript :

<style type="text/css">
       .domains-list .domain {
           cursor: pointer;
           padding: 1px 4px;
       .domains-list .selected {
           background: #222;
           color: #fff;
<script type="text/javascript">
       var toggle = function(domainEl) {
           var input = document.getElementById('h';
           if(domainEl.className.indexOf('selected') > -1) {
               domainEl.className = 'domain';
               input.value = '';
           } else {
               domainEl.className = 'domain selected';
               input.value =;

And then adapt the form components :

    <div class="domains-list">
       #{list domains, as:'domain'} 
           <span id="${}" onclick="toggle(this)" 
                class="domain ${ ? 'selected' : ''}">
           <input id="h${}" type="hidden" name="" 
                    value="${ ? : ''}" />

USing checkboxes

Another choice is to use checkboxes. The use is really simple. The important thing is the same, use the good name on the form component : name=""

    #{list domains, as:'domain'} 
	<input id="${}" type="checkbox" name="" 
	         ${ ? 'checked' : ''} value=${}>${domain}</input>
    <input type="hidden" name="" value="" />

Updated : It’s important to not forgot the last <input /> to handle when no checkbox is selected, otherwise no changes will be made.


About this entry