7

私は IceFaces から PrimeFaces に変更しています (本当は RichFaces に変更したかったのですが、新しいバージョンでバグが発生したため変更しません)、primefaces autoComplete を正しく実装するのが困難です。彼のマニュアルによると、オブジェクトのリストを返すメソッドを実装する必要があるだけで、この場合はコンバーターが必要です。

私が返しているリストは、javax.faces.model.SelectItem のリストです。なぜこれへのコンバーターを作成する必要があるのか​​ 本当に理解できませんが、続けましょう。テスト用に単純なコンバーターを作成しましたが、primefaces はコンバーターを認識せず、ブラウザーに次のエラーを返します。

/resources/components/popups/popupBuscaPessoa.xhtml @35,41 itemLabel="#{pessoa.label}": クラス「java.lang.String」にはプロパティ「label」がありません。

これは私のconversorクラスです(テストするだけです):

public class ConversorSelectItem implements Converter {

@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {      
     if (value!=null && value.isEmpty())
         return null;

     SelectItem selectItem=new SelectItem();
     selectItem.setLabel(value);
     return selectItem;     
}

@Override
public String getAsString(FacesContext context, UIComponent component, Object object) {
    return ((SelectItem)object).getLabel();
}
}

これは私が p:autocomplete: を使用しようとする場所です:

<p:autoComplete value="#{modeloPopupBuscaPessoa.itemSelecionado}"
            completeMethod="#{controladorSugestaoPessoa.atualizarSugestoes}"
            var="pessoa" itemLabel="#{pessoa.label}" itemValue="#{pessoa.value}"
            converter="#{conversorSelectItem}"/>

私は何か間違ったことをしましたか?SelectItem の既定のコンバーターはありませんか? このコンバーターを実装する簡単な方法はありますか?

4

5 に答える 5

12

を与えてはいけませんList<SelectItem>。あなたはそれを養うべきList<Pessoa>です。また、変換に集中しないでくださいSelectItem。アイテム値の変換に集中する必要がありPessoaます。これSelectItemは、古い JSF 1.x 時代の名残りです。varJSF 2.x では、ビューの,itemValueおよびitemLabel属性のおかげで、これは必須ではなくなりました。これにより、ビュー固有の乱雑さから Bean をクリーンに保つことができます。

を使用し、がプロパティを参照するConverter場合にのみ必要です。次に、一意の表現に変換し (HTML で印刷できるようにするため)、変換元から( Bean プロパティに設定できるようにするため) する必要があります。itemValue="#{pessoa}"#{modeloPopupBuscaPessoa.itemSelecionado}PessoagetAsString()PessoaStringgetAsObject()StringPessoa

ただし、が であり、もである場合#{pessoa.value}は、Stringを使用して完全に削除する必要があります。#{modeloPopupBuscaPessoa.itemSelecionado}StringitemValue="#{pessoa.value}"Converter

以下も参照してください。

于 2011-10-04T20:41:21.690 に答える
6

Primefaces オートコンプリートおよびその他すべての目的に使用できる汎用コンバーター:

import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.WeakHashMap;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;

@FacesConverter(value = "entityConverter")
public class EntityConverter implements Converter {

    private static Map<Object, String> entities = new WeakHashMap<Object, String>();

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object entity) {
        synchronized (entities) {
            if (!entities.containsKey(entity)) {
                String uuid = UUID.randomUUID().toString();
                entities.put(entity, uuid);
                return uuid;
            } else {
                return entities.get(entity);
            }
        }
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String uuid) {
        for (Entry<Object, String> entry : entities.entrySet()) {
            if (entry.getValue().equals(uuid)) {
                return entry.getKey();
            }
        }
        return null;
    }

}
于 2013-06-13T10:14:49.203 に答える
2

私は同じ問題に直面し、Primefaces autocomplete with POJO and String valueでの著者のコメントは、私の場合の問題の原因を見つけるためのヒントを与えてくれました。

概要

問題は、それvalue=#{objectValue}は型ですStringが、で参照されているメソッドcompleteMethodが を返していることList<Object>です。

デザイン

次のPOJOがあります(簡略化):

public class CollaboratorGroup {
   private String groupId;

   private String groupName;

   private Collaborator piUserId;

   ...
}

public class Collaborator {
   private String userId;

   private String fullName;

   private String groupId;
   ...
}

これが有用な設計であるかどうかは問題ではありません。問題に対処したいだけです。

以下p:autoComplete(簡略化):

<p:autoComplete var="group"
    itemLabel="#{group.groupId}"
    itemValue="#{group.groupId}"
    completeMethod="#{bean.completeGroup}"
    value="#{collaborator.groupId}">
    <f:facet name="itemtip">
        <p:panelGrid columns="2">
            <f:facet name="header">
                <h:outputText value="#{group.groupId}" />
            </f:facet>
            <h:outputText value="Name:" />
            <h:outputText value="#{group.groupName}" />
            <h:outputText value="PI" />
            <h:outputText value="#{group.piUserId.fullName}" />
        </p:panelGrid>
    </f:facet>
</p:autoComplete>

投げThe class 'java.lang.String' does not have the property 'groupId'ます。に変更すると、入力フィールドitemLabel=#{group}に groupId が表示されますが、その多くはドロップダウン リストに表示されます。これらのいずれかを選択すると、この値は望ましくない Collaborator.groupId に設定されます。CG00255org.coadd.sharedresources.model.CollaboratorGroup@...toString()

問題の原因

しばらくp:autoCompleteの間、とは、セット asとから生成されたの両方を「フォーマット」するために使用されます。List<CollaboratorGroup>Collaborator.groupIdStringitemLabelString groupIdvalue="#{collaborator.groupId}"CollaboratorGroupListcompleteMethod="#{bean.completeGroup}"

可能な解決策

  1. 設計を破壊しない場合Modelは、メンバgroupIdCollaboratorGroupin に変更することで を調整できます。Collaboratorこの場合、特にCollaboratorGroupmemberと同様Collaborator piUserIdです。
  2. p:autoCompleteをで埋めることもできList<String> groupIdListますが、この場合は の別の解決策を見つける必要がありますitemtip

  3. 非常に簡単な解決策は、 POJO と String valueitemLabel="#{group.class.simpleName eq 'String' ? group : group.groupId}"を使用した Primefaces autocomplete で説明されているように使用することです。

    • 問題
      • あなたは気にする必要がありますNullPointerExceptions
      • あなたViewは論理であなたを埋めます。
      • 非常に柔軟または動的な設計ではありません。
  4. itemLabel="#{bean.printGroupId(group)}"ロジックを完全に制御できるBean メソッドで 3. を実装します。これが私がしたことです。

    public String printGroupId(Object group) {
        if (group == null) return null;
        return (group instanceof String) ? (String) group : (group instanceof CollaboratorGroup) ? ((CollaboratorGroup) group).getGroupId() : null;
    }
    

    (最高ではありません。アイデアを提供するだけです。)

于 2018-07-27T02:25:52.250 に答える
-1
 ELContext elContext = FacesContext.getCurrentInstance().getELContext();
 ItemBean itemBean = (ItemBean) elContext.getELResolver().getValue(elContext, null, "itemBean");
 for(Item item : itemBean.getItems()){
     if(item.getId().getItemCode().equals(value)){
         return item;
     }
 }
于 2016-02-22T10:53:40.007 に答える