Using rich:orderingList and rich:listShuttle components

rich:orderingList lets you arrange values by moving them up or down. It’s based on a data table component, so you can put any object inside with any number of “columns” or attributes shown.

orderingList

Code:

<rich:orderingList value="#{carsBean.allCars}" var="car"
  converter="carConverter">
	<rich:column>
		<h:facet name="header">Make</f:facet>
		<h:outputText value="#{car.make}"/>
	</rich:column>
	<rich:column>
		<f:facet name="header">Model</f:facet>
		<h:outputText value="#{car.model}"/>
	</rich:column>
</rich:orderingList>

The other component is rich:listShuffle. Notice that you can also order the values (move up/down) as in rich:orderingList

listShuffle

Code:

<rich:listShuttle sourceValue="#{carsBean.allCars}"
       targetValue="#{carsBean.selectedCars}"
       var="car"
       listsHeigth=300
       sourceListWidth="300"
       targetListWidth="300"
       sourceCaptionLabel="Available Cars"
       targetCaptionLabel="Currently Active Cars"
       converter="carConverter">
	<rich:column>
		<h:outputText value="#{car.make}"/>
	</rich:column>
	<rich:column>
		<h:outputText value="#{car.model}"/>
	</rich:column>
</rich:listShuttle>

If you know how to use h:dataTable, you should be able to use these components easily, without even referring to the developer guide.

One thing to keep in mind is that if you are using objects other than String (or primitives), you need to write a custom converter to convert the values from text to custom object type. You also have to overwrite the equal() method in your custom object. Here is how mine looks for the above examples:

@Override
public boolean equals(Object obj) {
    CarItem ci = (CarItem)obj;
    if ( this.make.equals(ci.getMake()) &&
         this.model.equals(ci.getModel()))
    	return true;
    else
    	return false;
}

Published by

8 responses to “Using rich:orderingList and rich:listShuttle components”

  1. I Like the listShuttle control, but I have a few comments:

    1. Above you call it listSuffle, then listShuttle in the code example.
    2. I think the copy and copy all is missleading, it really does a move. Luckily I was able to change the labels and call it a move for my page, the tester freaked when it didn’t leave the item behind when it said move. I prefer the move.
    3. If possible could you show the example of the converter. I did not need one as I used 2 Sting lists.

    It is a nice user friendly control. In my case I have a page where they specify sort values for a process. I pre-populated the current list with a set of string defaults and the available list with the remainder of the string sort values that are available. In many cases the user will accept what is in the list without any selection. the original design spec I had had all the sort items as a list with a check box next to the fields and then a sort order long value. It was ugly and hard on the user, so I used your listShuttle control and the analyst went..WOW

    Thanks

  2. 1) That’s a typo, sorry.

    2) You are correct, I created a Jira issue some time ago: https://jira.jboss.org/browse/RF-8552 . I hope this is fixed in RichFaces 4

    3) Here is a converter for Airline object:

    public class AirlineConverter
    implements javax.faces.convert.Converter{
    
       public Object getAsObject(FacesContext context, UIComponent component,
    			String value) {
    	String[] words = value.split(":");
    	String name = words[0];
    	String code = words[1];
    	Airline airline = new Airline(name, code);
    	return airline;
       }
    
       public String getAsString(FacesContext context, UIComponent arg1, Object value) {
    	return value.toString();
       }
    }
    
    public class Airline implements java.io.Serializable {
    
    	private String name;
    	private String code;
    	private String logoImage;
    
    
    	public Airline(String name, String code) {
    		super();
    		this.name = name;
    		this.code = code;
    		this.logoImage = "/images/air.png";
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public String getCode() {
    		return code;
    	}
    
    	public void setCode(String code) {
    		this.code = code;
    	}
    
    	public String getLogoImage() {
    		return logoImage;
    	}
    
    	public void setLogoImage(String logoImage) {
    		this.logoImage = logoImage;
    	}
    
    	public String toString() {
    		return name   ":"   code;
    	}
    
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result   ((code == null) ? 0 : code.hashCode());
    		result = prime * result
    				  ((logoImage == null) ? 0 : logoImage.hashCode());
    		result = prime * result   ((name == null) ? 0 : name.hashCode());
    		return result;
    	}
    
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		final Airline other = (Airline) obj;
    		if (code == null) {
    			if (other.code != null)
    				return false;
    		} else if (!code.equals(other.code))
    			return false;
    		if (logoImage == null) {
    			if (other.logoImage != null)
    				return false;
    		} else if (!logoImage.equals(other.logoImage))
    			return false;
    		if (name == null) {
    			if (other.name != null)
    				return false;
    		} else if (!name.equals(other.name))
    			return false;
    		return true;
    	}
    	private static final long serialVersionUID = 1L;
    }
    
  3. Thanks Max, you are always a fast resonder.

    One other thing above, the example of the xhtml uses listHeight=”300″ and
    listWidth=”300″, these should be listsHeigth=300 sourceListWidth=”300″ targetListWidth=”300″, then it will be all up to date,

    Thanks

  4. @Ron: thanks, updated.

  5. Hi

    what about a converter that escapes chars like ‘:’?

    what chars should I escape?

    TIA

  6. @Leo K: I’m not sure I understand the question. A converter is doing text –> object and object –> text. Can you provide an example of what you are trying to do?

  7. Sure

    suppose I write a converter like this

    private static final char SEPARATOR = ‘:’;

    private static final long serialVersionUID = 1L;

    @Override
    public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
    String id = arg2.substring(0, arg2.indexOf(SEPARATOR));
    String desc = arg2.substring(arg2.indexOf(SEPARATOR) 1, arg2.length());
    PerguntaHelper ph = new PerguntaHelper();
    ph.setCoSeqPergunta(Integer.valueOf(id));
    ph.setDsPergunta(desc);
    }

    @Override
    public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
    PerguntaHelper ph = (PerguntaHelper) arg2;
    return ph.getCoSeqPergunta() SEPARATOR ph.getDsPergunta();
    }

    Won´t work because ‘:’ must be escaped, otherwise, it will mess with the internal IDs that richfaces uses. In fact, I am not even sure what chars should I escape.

  8. @Leo K: it’s probably a better idea to use a different separator, such as _. This way you don’t have to do anything extra.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.