2014-11-05 1 views
2

primefaces p : autoComplete 구성 요소가 포함 된 JSF 양식을 작성 중입니다. 다음은 autoComplete 구성 요소에 대한 관련 정보를 표시하는 내 xhtml 페이지의 압축을 푼 것입니다. Primefaces p : POJO의 String 필드에 대한 자동 완성 문제

<p:autoComplete 
    value="#{curAttribute.value}" 
    completeMethod="#{newBacking.lookupActivated}" 
    var="curEntry" 
    itemLabel="#{curEntry.classname}" 
    itemValue="#{curEntry.id}" 
    emptyMessage="Start typing..."/> 

curAttributeCosmoAttribute 클래스의 인스턴스주의하십시오, 그리고 CosmoAttribute.value하는 문자열 (물론, CosmoAttribute이 필드에 대한 모든 getter 및 setter를 가지고)입니다.

newBacking.lookupActivated() 메서드는 List<CosmoCard>을 반환합니다.

CosmoCard.classnameCosmoCard.id은 모두 문자열입니다.

나는 POJOs로 woirking하고 있지만, 모든 값은 POJO의 String 필드이므로, 나는 변환기가 필요하다고 생각하지 않는다. 어쨌든, 내 자동 완성 필드는 잘 작동하지만 내가 항목을 선택하면, 다음과 같은 예외가 :

SEVERE: Error Rendering View[/test.xhtml] 
javax.el.PropertyNotFoundException: /test.xhtml @98,68 itemLabel="#{curEntry.id}": The class 'java.lang.String' does not have the property 'id'. 
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:111) 
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194) 
    at org.primefaces.component.autocomplete.AutoComplete.getItemLabel(AutoComplete.java:148) 
    . 
    . 

Caused by: javax.el.PropertyNotFoundException: The class 'java.lang.String' does not have the property 'id'. 
    at javax.el.BeanELResolver.getBeanProperty(BeanELResolver.java:730) 
    at javax.el.BeanELResolver.getValue(BeanELResolver.java:351) 
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176) 
    . 
    . 

사람 내가 잘못 뭐하는 거지의 단서습니까? very similar question here을 찾을 수는 있지만 불행히도 답이 없습니다. 나는 내 코드에 대해 더 자세히 설명하고자한다.

UPDATE : 사실

, 모든 것이 잘 작동 : 자동 완성 : 나는 페이지의 드롭 다운에서 올바른 값을 참조하십시오. 내가 값을 선택하면, backing 빈 (newBacking)의 데이터가 그에 따라 업데이트됩니다. 그러나 예외를 제거 할 수는 없지만 내 페이지 실행에 영향을 미치지는 않습니다.

태그의 제약 조건을 존중합니다. 즉 value 속성과 itemValue는 동일한 유형 (두 문자열)입니다. 제대로되지 않은 유일한 점은 시스템이 목록의 목록을 변환하려고 시도하는 것입니다. 이유 또는 시점을 모르지만 변환의 실패 (및 후속 예외)가 해당 목록에 영향을 미치지 않습니다. 내 페이지의 동작.

UPDATE : 여기서

very simplified version of the project (넷빈즈)에 연결된다. 프로젝트의 관련 파일도 아래에 나열되어 있습니다.

test.xhtml

<h:body> 
    <h:form id="form"> 
     <p:dataTable var="curAttribute" value="#{newBacking.card.attributes}"> 
      <p:column > 
       THE CURSED FIELD <br /><br /> 

       <p:autoComplete 
        value="#{curAttribute.value}" 
        completeMethod="#{newBacking.lookupActivated}" 
        var="curEntry" 
        itemLabel="#{curEntry.code}" 
        itemValue="#{curEntry.id}"> 
       </p:autoComplete> 
      </p:column> 
     </p:dataTable> 
    </h:form>  

newBacking.java

@Named() 
@SessionScoped 
public class NewBacking implements Serializable { 

    private CosmoCard card; 

    private String currentCardClassname = ""; 

    @PostConstruct 
    public void init() { 

     Random randomGenerator = new Random(); 
     card = new CosmoCard(); 
     card.setId("ID" + randomGenerator.nextInt(1000)); 

     CosmoAttribute myLA = new CosmoAttribute(); 
     myLA.setLabel("LookupAttributeLabel"); 
     myLA.setValue("LookupAttributeValue"); 
     card.getAttributes().add(myLA); 
    } 

    public CosmoCard getCard() { 
     return card; 
    } 

    public String getCurrentCardClassname() { 
     return currentCardClassname; 
    } 

    public void setCurrentCardClassname(String currentCardClassname) { 
     this.currentCardClassname = currentCardClassname; 
    } 

    public List<CosmoCard> lookupActivated(String tgtQuery) { 

     Logger.getLogger(NewBacking.class.getName()).info("[NewBacking.lookupActivated()] Query: " + tgtQuery); 
     return CosmoCardList.generateCardList(10).getCards(); 
    } 

} 
+0

)는 p : autocomplete 태그의 값으로 간주되며, 완료 메소드 (CosmoCard)가 리턴하는 것과 같은 유형은 아닙니다.2) 변환기를 사용하지 않으면 complete 메서드가 List 을 반환합니다. 3) 변환기를 사용하더라도 시스템은 CosmoAttribute 대신 CosmoCard를 배치하여 값을 할당하려고합니다. 나는 완전한 메소드의 리턴 타입으로리스트 을 사용할 것이라고 생각하기 시작했다. 라벨과 값을 구분하는 구분 기호가있을 수 있습니다. – INElutTabile

+1

제 생각에는 당신이 분명히 당신이 사용하는 것을 반환해야합니다. 따라서 문제는 2와 3을 일으키는 첫 번째 추론 때문입니다. 분리자를 사용하고 반환 된 문자열을 처리하는 것과 같은 작업은 좋은 습관이 아닙니다. – Pumpkin

+0

내 생각을 정확히 (분리 물에 관한 것). 그렇다면 p : autocomplete와 complete 메소드의 반환 유형 모두에서 동일한 유형의 POJO를 사용해야하는 것 같습니다. 맞습니까? 그래서 나는 변환기를 사용하는 데 아무런 문제가 없다. 나는 다른 해결책을 보지 못했다. – INElutTabile

답변

3

완전한 방법은 복잡한 클래스의 인스턴스를 반환하여 당신은 컨버터가 필요합니다. 변환기가 존재하지 않는다면 구성 요소는 문자열로 작업하고 가치 및 레이블 속성을 가져올 때 참조를 제공하려고한다고 생각합니다. (CosmoAttribute를 1) POJO이를 사용하여 시도하고 작동하는지 볼 수 있지만 난 강력하게 필요에 따라 자신의 컨버터를 만드는 것이 좋습니다 내가 다음과 같은 이유로 POJO 방식을 사용할 수 없다는 것 @Pumpkin

@FacesConverter("anySelectConverter") 
public class AnySelectConverter implements Converter{ 


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

     @Override 
     public String getAsString(FacesContext context, UIComponent component, Object entity) { 

      // TODO : Fix 
      if(entity == null) 
       return ""; 

      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; 
     } 

    } 
+1

변환기를 사용하려고하면 실제로 변환기 사용을 피하는 방법을 찾고있었습니다. 프라임 머티리얼은 완전한 메소드의 출력으로 "단순한"클래스만을 받아들입니까? – INElutTabile

+0

문자열 만 허용하므로 변환기 사용은 필수 항목이되며 대신 수동으로 모든 작업을 수행해야합니다. 필자는 상대적으로 중요한 구성 요소에 대해서는 거의 사용되지 않는 기본 구성 요소 및 사용자 지정 변환기에 대한 anySelectConverter를 만드는 것이 좋습니다. – Pumpkin

+0

질문의 코멘트 영역에 답합니다. – INElutTabile