Modifying Multiple Selection Rows
brianc.brian.700c.net Nov 10, 2009 9:13 AMI have a scrollableDataTable that contains a List of NodeFile objects, which is a wrapper around a File entity. A button (rename), when clicked, calls processDetailSelection which processes the selection and creates a list of FileNodes to work with. A modelPanel is brought up with the list of fileNodes bound to the name property in an <h:inputText> boxe. The user is asked to rename the files. When done, they click on a button that calls renameSelected. 
The problem I am having is that the renamed names are not getting assigned the changed values on postback.
Any ideas are appreciated!
...
     <h:form>
          <rich:toolBar height="34" itemSeparator="line"> 
               <rich:toolBarGroup>
                    <a:commandLink id="rename"
                         action="#{fileManager.processDetailSelection}"  
                         oncomplete="#{rich:component('renamePanel')}.show();" 
                         reRender = "renamePanel">
                         <h:graphicImage id="renameIcon" value="/img/rename.gif" />
                         <h:outputLabel value="Rename" for="renameIcon" />
                    </a:commandLink>
               </rich:toolBarGroup>
          </rich:toolBar>
     </h:form>
          
     <h:panelGrid columns="2" rowClasses="fmGrid">
          <h:panelGroup>
...
            <h:form>
               <rich:scrollableDataTable
                 value="#{detailFiles}" var="_file"
                width="580px" height="400px"
                    id="detailFiles"
                    binding="#{fileTable}"
                    sortOrder="#{fileManager.detailSortOrder}"
                    sortMode="single"
                selection="#{fileManager.detailSelection}">
                <rich:column
                     id="name" 
                     width="170px">
                     <f:facet name="header">
                         <h:outputText value="Name" />
                    </f:facet>
                     <ui:remove><!--  <h:graphicImage value="#{_file.type.icon}" /> --></ui:remove>
                     <h:outputText value="#{_file.name}" />
                </rich:column>
... more columns...
            </rich:scrollableDataTable>
          </h:form>     
          </h:panelGroup>
     </h:panelGrid>
  
     <rich:modalPanel id="renamePanel"
          width="400" height="150"
          autosized="true">
         <f:facet name="header">
               <h:outputText value="Rename?"></h:outputText>
          </f:facet>
          <f:facet name="controls">
               <span style="cursor:pointer" onclick="javascript:Richfaces.hideModalPanel('renamePanel')">X</span>
          </f:facet>
          <h:outputText value="Rename files?" />
          <h:form>
               <rich:dataList value="#{fileManager.detailSelected}" var="_sel" rows="10">
                    <h:outputText value="#{_sel.name}"/>: <rich:spacer height="1" width="2" />
                    <h:inputText id="name" value="#{_sel.file.fileName}" /><br/>
               </rich:dataList>
               <s:button value="Yes" reRender="tree, detailFiles" 
                action="#{fileManager.renameSelected}" 
                oncomplete="javascript:Richfaces.hideModalPanel('renamePanel');" />
               <s:button value="Cancel" 
                oncomplete="javascript:Richfaces.hideModalPanel('renamePanel');" />
          </h:form>
     </rich:modalPanel>
...
My backing Bean
package com.projectSpace.action;
//imports removed to save space
@Name("fileManager")
@Scope(ScopeType.CONVERSATION)
public class FileManager implements Serializable {
     @In(create = true)
     ProjectHome projectHome;
     @In 
     protected EntityManager entityManager;
     @In
     FacesMessages facesMessages;
     @RequestParameter 
     protected Integer projectId;
     private static final long serialVersionUID = 6484170532121358284L;
     // Tree Variables
     public FileNode selectedNode;
     private List<FileNode> fileRoots = new ArrayList<FileNode>();
     // Detail Variables
     @DataModel
     protected List<FileNode> detailFiles;
     private SimpleSelection detailSelection;
     private ArrayList<FileNode> detailSelected = new ArrayList<FileNode>(0);
     private SortOrder detailSortOrder;
     @In(required = false) 
     @Out(required = false) 
     private HtmlScrollableDataTable fileTable;
     private String tableState;
     private boolean deleteFailed = false;
     @Transactional
    public String renameSelected(){
         if (this.detailSelected.isEmpty()) {
              return "noSelection";
         }
         else {
              try {
                   Iterator<FileNode> iterator = getDetailSelected().iterator();
                   while (iterator.hasNext()){
                        FileNode fileNode = iterator.next();
                        log.info("Renaming: fileNode.name= " + 
                                  fileNode.getName() + 
                                  ", fileNode.file.fileName = " + 
                                  fileNode.getFile().getFileName());
                        entityManager.flush();
                   } 
                   renamedMessage();
                   this.refresh();
                  return "renamed";
              } catch (Exception e) {
                   facesMessages.add("The selected files could not be renamed");
                   return null;
              }
         }
    }
    public String processDetailSelection() {
         if (this.detailSelection.size() !=0) {
             this.detailSelected.clear();
            Iterator<Object> iterator = getDetailSelection().getKeys();
            while (iterator.hasNext()){
                 Integer key = (Integer) iterator.next();
                 this.detailSelected.add(getDetailFiles().get(key.intValue()));
            }              
         }
        return null;
    }
...
}
The FileNode
@Name("FileNode")
@Scope(ScopeType.CONVERSATION)
public class FileNode implements Serializable {
     private static final long serialVersionUID = 7729590153661819332L;
     private File file;
     private static List<FileNode> CHILDREN_ABSENT = new ArrayList<FileNode>(0);
     private List<FileNode> childFolders;
     private List<FileNode> childFiles;
     private String name;
     private FileNode parent;
     
     public FileNode(File file) {
          this.file =  file;
          this.setName(file);
     }
     public FileNode(File file, FileNode parent) {
          this.file =  file;
          this.setName(file);
          this.setParent(parent);
     }
     
     public String getName(){
          return this.name;
     }
     
     public void setName(File file){
          if (file.getFileName().equals("ROOT"))
               this.name = file.getProject().getProjectNumber() + " - " + file.getProject().getName();
          else
               this.name = file.getFileName();
     }
     public void setName(String name){
          if (this.file.getFileName().equals("ROOT"))
               return;  // we cannot rename the project. 
                         // TODO probably should throw an exception or warn user.
          else {
               this.name = name;
               this.file.setFileName(name);
          }
     }
     
     public File getFile() {
          return this.file;
     }
     
     public void setFile(File file) {
          this.file = file;
     }
....
}
And Finally, the File Entity
@Entity
@Table(name = "files")
public class File implements java.io.Serializable {
     private static final long serialVersionUID = -8800801738264510972L;
     private Long id;
     private Project project;
     private String fileName;
     private Date dateCreated;
     private Date dateModified;
     private Type type;
     private Boolean folder = false;
     private File parent;
     private Set<File> subFiles = new HashSet<File>();
     private Set<FileRevision> fileRevisions = new HashSet<FileRevision>();
     @In
     private EntityManager entityManager;
     public File() {
     }
...
getters/setters
...
} 
 
    