RichFaces 4中的ExtendedDataTable:DataModel处理 [英] ExtendedDataTable in RichFaces 4: DataModel handling

查看:46
本文介绍了RichFaces 4中的ExtendedDataTable:DataModel处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我还有一个问题,与我在一月份发布的问题有些相关.我有一个列表,它是rich:extendedDataTable组件,它会随着用户在一个单独的文本框中键入他的搜索条件而动态更新(即,用户输入前4个字符,并且在他不断键入时会显示结果)列表更改).最后,当我使用RichFaces 3时,它工作正常,但是当我升级到RichFaces 4时,我遇到了各种各样的编译问题.似乎无法再访问以下类,并且似乎没有合适的替代品:

I have another question, somewhat related to the one I posted in January. I have a list, which is rich:extendedDataTable component, and it gets updated on the fly, as the user types his search criteria in a separate text box (i.e. the user types in the first 4 characters and as he keeps typing, the results list changes). And in the end it works fine, when I use RichFaces 3, but as I upgraded to RichFaces 4, I've got all sorts of compilation problems. The following classes are no longer accessible and there no suitable replacement for these, it seems:

org.richfaces.model.DataProvider
org.richfaces.model.ExtendedTableDataModel
org.richfaces.model.selection.Selection
org.richfaces.model.selection.SimpleSelection

这是以前的样子:

这是应该触发搜索逻辑的输入文本:

This is the input text that should trigger the search logic:

<h:inputText id="firmname" value="#{ExtendedTableBean.searchValue}">
   <a4j:support ajaxSingle="true" eventsQueue="firmListUpdate"  
                reRender="resultsTable" 
                actionListener="#{ExtendedTableBean.searchForResults}" event="onkeyup" />
</h:inputText>

动作侦听器是应该更新列表的对象.这是inputData下方的extendedDataTable:

Action listener is what should update the list. Here is the extendedDataTable, right below the inputText:

<rich:extendedDataTable tableState="#{ExtendedTableBean.tableState}" var="item"
                       id="resultsTable" value="#{ExtendedTableBean.dataModel}">

        ... <%-- I'm listing columns here --%>

</rich:extendedDataTable>

这是后端代码,我在其中使用数据模型处理:

And here's the back-end code, where I use my data model handling:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.beans;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.richfaces.model.DataProvider;
import org.richfaces.model.ExtendedTableDataModel;

public class ExtendedTableBean {      
    private String sortMode="single";
    private ExtendedTableDataModel<ResultObject> dataModel;
    //ResultObject is a simple pojo and getResultsPerValue is a method that 
    //read the data from the properties file, assigns it to this pojo, and
    //adds a pojo to the list 

    private Object tableState;
    private List<ResultObject> results = new CopyOnWriteArrayList<ResultObject>();
    private List<ResultObject> selectedResults = 
                                      new CopyOnWriteArrayList<ResultObject>();

    private String searchValue;

    /**
     * This is the action listener that the user triggers, by typing the search value
     */
    public void searchForResults(ActionEvent e) {
       synchronized(results) {
           results.clear();
       }        

       //I don't think it's necessary to clear results list all the time, but here
       //I also make sure that we start searching if the value is at least 4 
       //characters long
       if (this.searchValue.length() > 3) {
           results.clear();
           updateTableList();
       } else {
           results.clear();
       }

       dataModel = null; // to force the dataModel to be updated.
    }

    public List<ResultObject> getResultsPerValue(String searchValue) {
        List<ResultObject> resultsList = new CopyOnWriteArrayList<ResultObject>();

        //Logic for reading data from the properties file, populating ResultObject
        //and adding it to the list

        return resultsList;
    }

    /**
     * This method updates a firm list, based on a search value
     */
    public void updateTableList() {
        try {              
            List<ResultObject> searchedResults = getResultsPerValue(searchValue);

            //Once the results have been retrieved from the properties, empty 
            //current firm list and replace it with what was found.

            synchronized(firms) {
                firms.clear();
                firms.addAll(searchedFirms);
            }
        } catch(Throwable xcpt) {
            //Exception handling
        }
    }

    /**
     * This is a recursive method, that's used to constantly keep updating the 
     * table list.
     */
    public synchronized ExtendedTableDataModel<ResultObject> getDataModel() {
        try {
            if (dataModel == null) {
                dataModel = new ExtendedTableDataModel<ResultObject>(
                               new DataProvider<ResultObject>() {
                                   public ResultObject getItemByKey(Object key) {
                                       try {
                                           for(ResultObject c : results) {
                                               if (key.equals(getKey(c))){
                                                   return c;
                                               }
                                           }
                                       } catch (Exception ex) {
                                           //Exception handling
                                       }
                                       return null;
                                   }

                                   public List<ResultObject> getItemsByRange(
                                                 int firstRow, int endRow) {
                                       return Collections.unmodifiableList(results.subList(firstRow, endRow));
                                   }

                                   public Object getKey(ResultObject item) {
                                       return item.getResultName();
                                   }

                                   public int getRowCount() {
                                       return results.size();
                                   }
                              });
            }
        } catch (Exception ex) {
            //Exception handling    
        }

        return dataModel;
    }

    //Getters and setters 

}

现在,类ExtendedTableDataModel和DataProvider不再可用,我应该使用什么呢? RichFaces论坛声称实际上没有任何内容,并且开发人员几乎完全依靠自己(这意味着他们必须执行自己的实现).有人还有其他想法或建议吗?

Now that the classes ExtendedTableDataModel and DataProvider are no longer available, what should I be using instead? RichFaces forum claims there's really nothing and developers are pretty much on their own there (meaning they have to do their own implementation). Does anyone have any other idea or suggestion?

再次感谢您的所有帮助,对于一个冗长的问题,我们深表歉意.

Thanks again for all your help and again, sorry for a lengthy question.

推荐答案

您可以将数据模型转换为扩展抽象org.ajax4jsf.model.ExtendedDataModel,这实际上是与<rich:extendedDataTable/>一起使用的更健壮和高性能的数据模型.将现有模型粗略转换为下面的新模型(我决定使用现有的ExtendedDataModel<ResultObject>作为基础数据源,而不是results列表来演示转换):

You could convert your data model to extend the abstract org.ajax4jsf.model.ExtendedDataModel instead which actually is a more robust and performant datamodel for use with <rich:extendedDataTable/>. A rough translation of your existing model to the new one below (I've decided to use your existing ExtendedDataModel<ResultObject> as the underlying data source instead of the results list to demonstrate the translation):

   public class MyDataModel<ResultObject> extends ExtendedDataModel<ResultObject>{

    String currentKey; //current row in the model
    Map<String, ResultObject> cachedResults = new HashMap<String, ResultObject>(); // a local cache of search/pagination results
    List<String> cachedRowKeys; // a local cache of key values for cached items
    int rowCount;
    ExtendedTableDataModel<ResultObject> dataModel; // the underlying data source. can be anything


    public void setRowKey(Object item){
     this.currentKey = (ResultObject)item.getResultName();   
    }

    public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException {
    int firstRow = ((SequenceRange)range).getFirstRow();
    int numberOfRows = ((SequenceRange)range).getRows();
    cachedRowkeys = new ArrayList<String>();
    for (ResultObject result : dataModel.getItemsByRange(firstRow,numberOfRows)) {
       cachedRowKeys.add(result.getResultName());
       cachedResults.put(result.getResultName(), result); //populate cache. This is strongly advised as you'll see later.
       visitor.process(context, result.getResultName(), argument);
      }
    }

   }


 public Object getRowData() {
   if (currentKey==null) {
       return null;
   } else {
       ResultObject selectedRowObject = cachedResults.get(currentKey); // return result from internal cache without making the trip to the database or other underlying datasource
       if (selectedRowObject==null) {  //if the desired row is not within the range of the cache

           selectedRowObject = dataModel.getItemByKey(currentKey);
           cachedResults.put(currentKey, selectedRowObject);
           return selectedRowObject;
       } else {
           return selectedRowObject;
       }
   }

 public int getRowCount(){
 if(rowCount == 0){
    rowCount = dataModel.getRowCount(); //cache row count
    return  rowCount;
  }
  return rowCount

 }

那是该类中3个最重要的方法.还有很多其他方法,基本上可以从不需要担心的旧版本中继承下来.如果要将JSF状态保存到客户端,则可能对org.ajax4jsf.model.SerializableDataModel感兴趣,以便进行序列化.请参见此处的示例.这是一个老博客,但逻辑仍然适用.

Those are the 3 most important methods in that class. There are a bunch of other methods, basically carry over from legacy versions that you don't need to worry yourself about. If you're saving JSF state to client, you might be interested in the org.ajax4jsf.model.SerializableDataModel for serialization purposes. See an example for that here. It's an old blog but the logic is still applicable.

与此无关,您当前的getRowData实施在生产级应用中的效果会很差.是否必须遍历每个元素以返回结果?尝试更好的搜索算法.

Unrelated to this, your current implementation of getRowData will perform poorly in production grade app. Having to iterate thru every element to return a result? Try a better search algorithm.

这篇关于RichFaces 4中的ExtendedDataTable:DataModel处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆