The Richfaces Drag-n-Drop component suite includes three components: rich:dragSource, rich:dropTarget, and rich:dragIndicator.
This example demonstrates the basic features of the RichFaces drag and drop mechanism. You can mark several different components as 'draggable' with the rich:dragSource component and define drag types with the type attribute. Then, add corresponding drop zones with the rich:dropTarget and use the acceptType attribute to define which drop zone corresponds to the dragged elements.
<!DOCTYPE html> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich"> <h:outputStylesheet> .panelc { width:25%; } .valign { vertical-align:top; } .dropTargetPanel { width: 90%; } .footerClass { text-align: center; padding-top: 5px; } .rf-ind-drag { font-size:11px; cursor:pointer; width:100px; border:1px solid gray; padding:2px } .rf-ind-acpt { border:2px solid green } .rf-ind-rejt { border:2px solid red } </h:outputStylesheet> <h:form id="form"> <h:panelGrid columnClasses="panelc valign, valign, valign, valign" columns="4" width="100%"> <rich:panel style="width:133px"> <f:facet name="header"> <h:outputText value="Source List" /> </f:facet> <h:dataTable id="src" value="#{dragDropBean.source}" var="fm" footerClass="footerClass"> <h:column> <a4j:outputPanel layout="block" styleClass="rf-ind-drag"> <rich:dragSource type="#{fm.family}" dragValue="#{fm}" /> <h:outputText value="#{fm.name}" /> </a4j:outputPanel> </h:column> <f:facet name="footer"> <a4j:commandButton action="#{dragDropBean.reset}" value="Start Over" render="src,phptable,cftable,dnettable" /> </f:facet> </h:dataTable> </rich:panel> <rich:panel styleClass="dropTargetPanel"> <f:facet name="header"> <h:outputText value="PHP Frameworks" /> </f:facet> <rich:dropTarget acceptedTypes="php" dropValue="PHP" dropListener="#{dragDropEventBean.processDrop}" render="phptable, src" /> <h:dataTable id="phptable" value="#{dragDropBean.targetPHP}" var="fm"> <h:column> <h:outputText value="#{fm.name}" /> </h:column> </h:dataTable> </rich:panel> <rich:panel styleClass="dropTargetPanel"> <f:facet name="header"> <h:outputText value=".NET Frameworks" /> </f:facet> <rich:dropTarget acceptedTypes="dotNet" dropValue="DNET" dropListener="#{dragDropEventBean.processDrop}" render="dnettable, src" /> <h:dataTable id="dnettable" value="#{dragDropBean.targetDotNet}" var="fm"> <h:column> <h:outputText value="#{fm.name}" /> </h:column> </h:dataTable> </rich:panel> <rich:panel styleClass="dropTargetPanel"> <f:facet name="header"> <h:outputText value="ColdFusion Frameworks" /> </f:facet> <rich:dropTarget acceptedTypes="cf" dropValue="CF" dropListener="#{dragDropEventBean.processDrop}" render="cftable, src" /> <h:dataTable id="cftable" value="#{dragDropBean.targetCF}" var="fm"> <h:column> <h:outputText value="#{fm.name}" /> </h:column> </h:dataTable> </rich:panel> </h:panelGrid> </h:form> <a4j:outputPanel ajaxRendered="true"> <h:messages /> </a4j:outputPanel> </ui:composition>
package org.richfaces.demo.dragdrop; import static org.richfaces.demo.dragdrop.Framework.Family.cf; import static org.richfaces.demo.dragdrop.Framework.Family.dotNet; import static org.richfaces.demo.dragdrop.Framework.Family.php; import java.io.Serializable; import java.util.Collection; import java.util.List; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; import org.richfaces.demo.dragdrop.Framework.Family; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; @ManagedBean @ViewScoped public class DragDropBean implements Serializable { private static final long serialVersionUID = 1416925735640720492L; private static final FrameworkFamilyPredicate CF_PREDICATE = new FrameworkFamilyPredicate(cf); private static final FrameworkFamilyPredicate DOT_NET_PREDICATE = new FrameworkFamilyPredicate(dotNet); private static final FrameworkFamilyPredicate PHP_PREDICATE = new FrameworkFamilyPredicate(php); private static final class FrameworkFamilyPredicate implements Predicate<Framework> { private Framework.Family family; public FrameworkFamilyPredicate(Family family) { super(); this.family = family; } public boolean apply(Framework input) { return family.equals(input.getFamily()); } } private List<Framework> source; private List<Framework> target; public DragDropBean() { initList(); } public Collection<Framework> getSource() { return source; } public Collection<Framework> getTarget() { return target; } public List<Framework> getTargetPHP() { return Lists.newLinkedList(Collections2.filter(target, PHP_PREDICATE)); } public List<Framework> getTargetDotNet() { return Lists.newLinkedList(Collections2.filter(target, DOT_NET_PREDICATE)); } public List<Framework> getTargetCF() { return Lists.newLinkedList(Collections2.filter(target, CF_PREDICATE)); } public void moveFramework(Framework framework) { source.remove(framework); target.add(framework); } public void reset() { initList(); } private void initList() { source = Lists.newArrayList(); target = Lists.newArrayList(); source.add(new Framework("Flexible Ajax", php)); source.add(new Framework("ajaxCFC", cf)); source.add(new Framework("AJAXEngine", dotNet)); source.add(new Framework("AjaxAC", php)); source.add(new Framework("MonoRail", dotNet)); source.add(new Framework("wddxAjax", cf)); source.add(new Framework("AJAX AGENT", php)); source.add(new Framework("FastPage", dotNet)); source.add(new Framework("JSMX", cf)); source.add(new Framework("PAJAJ", php)); source.add(new Framework("Symfony", php)); source.add(new Framework("PowerWEB", dotNet)); } }
The rich:dragSource component defines the JSF component that becomes draggable. If you want to add a draggable feature to an existing component, attach rich:dragSupport as a child component.
The rich:dropTarget component is used to define the drop zone. The rich:dropTarget component has a built-in Ajax support: it can send an Ajax request and render the specified area on a page when the Ajax response is returned.
The rich:dragIndicator is a visual representation of a dragged object. The markup can be defined the markup of the indicator using nested components. By default, if the component is not defined a copy of the dragged elements are created.
Note that the parent component for the rich:dragSource and rich:dropTarget components should be designed to render its children, and should have the mouseover and mouseout event attributes. You can use a4j:outputPanel as a container if the component does not satisfy these requirements. Use <a4j:outputPanel layout="block"> to wrap the component with a block layout.
The following example demonstrates the drag-and-drop functionality in practice. The left list contains the examples of Ajax frameworks. Do you know them? The demonstration helps you to sort them out. Drag an item over the headers of the other three panels. If the draggable framework is suitable for a certain framework family, it will be accepted and moved from the source list to the target list.