2017-05-30 94 views
0

我在Custom UISelectOne组件中遇到问题。我的目的是创建包含自己数据的新自定义组件。所以我创建了组件的costactor方法中的虚拟数据访问,如下所示。当我把控件放在XHTML文件中时,它在第一次加载时工作正常,但是当我点击HTML页面的subbmit按钮时会出现错误并发出警告。错误和警告消息如下所示;JSF自定义UISelectOne回发错误;验证错误:值无效

顺便说一句,我看到了一些类似的问题。但他们中没有一个是关于定制控制的,我无法解决我的问题。正如我所说我想要在组件自己的承包商中加载数据。所以我认为我的情况看起来不一样。

) WARNING: FacesMessage(s) have been enqueued, but may not have been displayed. sourceId=j_idt6:j_idt7[severity=(ERROR 2), summary=(j_idt6:j_idt7: Validation Error: Value is not valid), detail=(j_idt6:j_idt7: Validation Error: Value is not valid)]

所以我的控制和格式化器代码:

@Named("ABankAccountList") 
@RequestScoped 
@FacesComponent(createTag = true, namespace = "http://abank.com.tr/example", tagName = "ABankAccountList", value = "com.abank.customcontrols.ABankAccountList") 
public class ABankAccountList extends UISelectOne { 



    private List<Account> accounts; 

    public ABankAccountList() { 

     this.setConverter(new AccountConverter()); 
     accounts=new ArrayList<Account>(); 
     Account tempAcc = null; 
     for (int i = 5; i < 8; i++) { 
      tempAcc = new Account(); 
      tempAcc.setAccountId(i); 
      tempAcc.setAccountNumber(i + "0456-789"); 
      tempAcc.setCurrencyCode("TRY"); 
      tempAcc.setIbanNumber("TR-" + i + "-98583213213223"); 
      accounts.add(tempAcc); 

     } 

    } 

    public List<Account> getAccounts() { 
     return accounts; 
    } 

    public void setAccounts(List<Account> accounts) { 
     this.accounts = accounts; 
    } 

    // After POST Back 
    @Override 
    public void decode(FacesContext context) { 


     super.decode(context); 


    } 

    @Override 
    public void encodeBegin(FacesContext context) throws IOException { 

     if (context.isPostback()) 
     { 
      return ; 

     } 

     UISelectItems selectItems = new UISelectItems(); 

     List<SelectItem> result = new ArrayList<SelectItem>(); 
     try { 

      for (Account account : accounts) { 
       SelectItem item = new SelectItem(account, account.getAccountNumber()); 
       result.add(item); 

      } 

     } catch (Exception e) { 
      // log.error("Failed to create enum list", e); 
     } 


     getChildren().clear(); 

     selectItems.setValue(result); 
     getChildren().add(selectItems); 






    } 

    // Render HTML 
    @Override 
    public void encodeEnd(FacesContext context) throws IOException { 


     super.encodeEnd(context); 
    } 



} 

另外我有如下一个Convertet类。 当我调试代码时,我注意到postBak后getAsObject方法触发两次。我不确定这是否正常?

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

    @Override 
    public Object getAsObject(FacesContext context, UIComponent uiComponent, String arg2) 
    { 

     ValueExpression vex = context.getApplication().getExpressionFactory() .createValueExpression(context.getELContext(),  
       "#{ABankAccountList}", ABankAccountList.class); 

     ABankAccountList contoller = (ABankAccountList)vex.getValue(context.getELContext()); 
     Account rAccount=null; 
     for (Account acc : contoller.getAccounts()) { 
       if (arg2.toString().equals(acc.getAccountId().toString())) { 
        rAccount = acc; 
       } 
      }   

      return rAccount; 
    } 

    @Override 
    public String getAsString(FacesContext arg0, UIComponent arg1, Object account) { 
     Account accctemp=((Account)account); 
     Integer accid=accctemp.getAccountId(); 
     return accid.toString(); 

    } 

} 

其实我不知道我应该在哪里加载数据和whreer应该设置Converter类。我明白的是;问题是因为回发之前和之后的数据匹配。但我不知道该怎么办?

最好的问候。

回答

0

嗨,我找到了解决方案。我已经覆盖了Value Class的equals方法。

@Override 
    public boolean equals(Object obj) { 
     if (obj == null) 
      return false; 
     if (obj instanceof Account) 
     { 
      Account other = (Account) obj; 
      if (other.getAccountId() == this.getAccountId() 
       && other.getIbanNumber() == this.getIbanNumber()  
        ) 
       return true; 
     } 
     return false; 
    }