Integrating drag and drop with data iteration components

The droppable component has a special integration with the data iteration components extending javax.faces.component.UIData. Such PrimeFaces components are dataTable, dataGrid, dataList, dataScroller, carousel, and ring. The component tag p:droppable defines a data source option as an ID of the data iteration component that needs to be connected with droppable.

In this recipe, we will introduce a dataGrid component containing some imaginary documents and make these documents draggable in order to drop them onto a recycle bin. The dataGrid component will act as a data source for the droppable Recycle Bin.

How to do it…

For the purpose of better understanding the developed code, pictures come first. The first screenshot shows what happens when we start to drag a document. The Recycle Bin area gets highlighted as follows:

How to do it…

What it looks like after dropping three documents onto the Recycle Bin is reproduced in the following screenshot:

How to do it…

Available documents are represented as images within p:dataGrid. They are placed in the panel components, which are made draggable. The dragging occurs via the panel's titlebar. The titlebar contains the document's title (name). The recycle bin is represented by a p:fieldset tag with the ID deletedDocs. Fieldset is made droppable. It also contains a p:dataTable with the currently deleted document items. Whenever a document is being dragged and dropped into the Recycle Bin, an AJAX listener is invoked. In the listener, the dropped document is removed from the list of all available documents and added to the list of deleted documents. Data iteration components will be updated after that in order to display the correct data. The code snippet, in XHTML, looks as follows:

<p:fieldset legend="Available Documents">
  <p:dataGrid id="availableDocs" columns="3" var="doc"
    value="#{integrationDragDrop.availableDocs}">
    <p:column>
      <p:panel id="pnl" header="#{doc.title}"
        style="text-align:center">
        <h:graphicImage library="images"
          name="dragdrop/#{doc.extension}.png"/>
      </p:panel>
      <p:draggable for="pnl" revert="true"
        handle=".ui-panel-titlebar"
        stack=".ui-panel" cursor="move"/>
    </p:column>
  </p:dataGrid>
</p:fieldset>

<p:fieldset id="deletedDocs" legend="Recycle Bin" style="margin-top:20px">
  <p:outputPanel id="dropArea">
    <h:outputText value="Drop documents into the recycle bin to delete them"
      rendered="#{empty integrationDragDrop.deletedDocs}"
      style="font-size:20px;"/>

    <p:dataTable var="doc"
      value="#{integrationDragDrop.deletedDocs}"
      rendered="#{not empty integrationDragDrop.deletedDocs}">

      <p:column headerText="Title">
        <h:outputText value="#{doc.title}"/>
      </p:column>
      <p:column headerText="Size (bytes)">
        <h:outputText value="#{doc.size}"/>
      </p:column>
      <p:column headerText="Creator">
        <h:outputText value="#{doc.creator}"/>
      </p:column>
      <p:column headerText="Creation Date">
        <h:outputText value="#{doc.creationDate}">
          <f:convertDateTime pattern="dd.MM.yyyy"/>
        </h:outputText>
      </p:column>
    </p:dataTable>
  </p:outputPanel>
</p:fieldset>

<p:droppable id="droppable" for="deletedDocs" tolerance="touch"
  activeStyleClass="ui-state-highlight"
  datasource="availableDocs">
  <p:ajax listener="#{integrationDragDrop.onDocumentDrop}"
    update="dropArea availableDocs"/>
</p:droppable>

The model class Document contains the document properties.

public class Document implements Serializable {

  private String title;
  private int size;
  private String creator;
  private Date creationDate;
  private String extension;

  public Document(String title, int size, String creator,
    Date creationDate, String extension) {
    this.title = title;
    this.size = size;
    this.creator = creator;
    this.creationDate = creationDate;
    this.extension = extension;
  }

  // getters / setters
  ...
}

The bean IntegrationDragDrop creates available documents (they can be loaded from a document management system, database, or filesystem), holds two lists for the data iteration components, and provides the AJAX listener onDocumentDrop.

@Named
@ViewScoped
public class IntegrationDragDrop implements Serializable {

  private List<Document> availableDocs =
    new ArrayList<Document>();
  private List<Document> deletedDocs =
    new ArrayList<Document>();

  @PostConstruct
  public void initialize() {
    availableDocs.add(new Document("Perl script", 120,
      "Sara Schmidt", getCreationDate(), "perl"));
    ...
  }

  public List<Document> getAvailableDocs() {
    return availableDocs;
  }

  public List<Document> getDeletedDocs() {
    return deletedDocs;
  }

  public void onDocumentDrop(DragDropEvent ddEvent) {
    Document doc = (Document) ddEvent.getData();
    deletedDocs.add(doc);
    availableDocs.remove(doc);
  }

  private Date getCreationDate() {
    Random random = new Random();
    int day = random.nextInt(30);
    int month = random.nextInt(Calendar.DECEMBER + 1);
    int year = 2014;
    GregorianCalendar calendar =
      new GregorianCalendar(year, month, day);

    return calendar.getTime();
  }
}

How it works…

We make the second p:fieldset tag droppable, and connect it to the p:dataList tag with the ID availableDocs. This is done by setting datasource to availableDocs on p:droppable. The AJAX listener onDocumentDrop, attached by the p:ajax tag, is invoked on the drop event. Thanks to datasource, we can now access the dropped document instance in the listener: Document doc = (Document)ddEvent.getData().

PrimeFaces Cookbook Showcase application

This recipe is available in the demo web application on GitHub (https://github.com/ova2/primefaces-cookbook/tree/second-edition). Clone the project if you have not done it yet, explore the project structure, and build and deploy the WAR file on every Servlet 3.x compatible application server, such as JBoss WildFly or Apache TomEE.

The showcase for the recipe is available at http://localhost:8080/pf-cookbook/views/chapter8/dragDropIntegration.jsf.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.166.149