2013-07-31 42 views
6

我試圖找出最佳做法綁定enum形成下拉式<select>在Play! 2.0綁定枚舉在Play中形成<select>元素!框架2.1

這裏是我的枚舉:

public enum ContactType { 
    CLIENT(1), 
    CONTRACTOR(2), 
    SUPPLIER(3); 

    public final int id; 

    ContactType(int id) { 
     this.id = id; 
    } 
} 

而且這是我想要得到的結果在我看來什麼:

<select name="contactType"> 
    <option value="1">CLIENT</option> 
    <option value="2">CONTRACTOR</option> 
    <option value="3">SUPPLIER</option> 
</select> 

回答

8

像這樣的事情在你的模板應該工作:

<select name="contactType"> 
    @for(cType <- ContactType.values()){ 
     <option value="@cType.id">@cType.name()</option> 
    } 
</select> 

注意:它可能會更好使用toString()而不是name()。如果在您的枚舉中覆蓋toString(),則可以返回承包商而不是承包商。

注2:如果你的枚舉不在models包,你需要用正確的包名即前綴是:@for(cType <- com.my_company.enums.ContactType)

+0

感謝。它適合我! :) – ainla

+0

@ainla不客氣。我手動添加了你的編輯,因爲他們被拒絕了,但我相信區分'type'(保留)和'cType'非常重要,謝謝指出! – Aerus

+0

@ainla,大家我們如何能夠爲任何枚舉類型創建一個視圖? –

16

假設你把選擇成HTML形式,它的方式是在我們的商店做的是我們一個Map添加到Java枚舉,然後使用由框架提供的選擇形式助手:

枚舉:

public enum ContactType { 
    CLIENT(1), 
    CONTRACTOR(2), 
    SUPPLIER(3); 

    public final int id; 

    ContactType(int id) { 
     this.id = id; 
    } 

    public static Map<String, String> options(){ 
     LinkedHashMap<String, String> vals = new LinkedHashMap<String, String>(); 
     for (ContactTypecType cType: ContactType.values()) { 
      vals.put(cType.id(), cType.name()); 
     } 
     return vals; 
    } 
} 

觀點:

@(contactForm: Form[models.Contact]) 

import helper._ 

<html><head></head><body> 
@helper.form(routes.Contact.formHandlerMethod()){ 
    @* 
    * Here contactForm("contactType") assumes that you want to map the 
    * ContactType selected to a field in a Contact class (which we've 
    * wrapped in play.data.Form<T> so that the fields in Contact become 
    * inputs in our form 
    *@ 
    @select(contactForm("contactType"), options(ContactType.options()) 
} 
</body></html> 

使用這種設計模式,你可以利用在play.data.Form類的輔助功能驗證,並在您聯繫控制器綁定表單數據和您從您的視圖具有較少的邏輯中獲益,並把邏輯在一個地方,它可以很容易地重新使用整個應用程序。

另一方面,如果您正在使用自己的選擇並以其他方式駕駛行動,那麼Aerus的答案可能是最直接的方法。

+0

謝謝!這也是一個非常優雅的解決方案。保持視圖代碼的清潔和乾淨。 – ainla

+1

不錯的解決方案,但你缺少靜態修改器:public static Map options() – cosmolev

+0

好的catch,@cosmolev。我沒有代表批准您的修改,但我會自己編輯它。 – 2manyprojects

4

編輯:表單不應該包括枚舉的所有類路徑,只是枚舉名稱。所以在ContactType類,put方法必須被替換到這一點:

  put(value.name(),name); 

我無法枚舉綁定到類。在控制器我有類似的東西:

public Result saveUser() { 
    Form<User> userForm = form(User.class).bindFromRequest(); 
    if(userForm.hasErrors()) { 
     return badRequest(createUser.render(userForm)); 
    } 
    User user=userForm.get(); 
    user.save(); 
    Logger.info(user.contacts.toString()); 
    flash("success", "User " + userForm.get().identity + " has been created"); 
    return GO_ADMIN; 
} 

這是一直返回我「error.invalid」。 的POST響應看起來像這樣:

identity=asas& 
status=1& 
contacts[0].name=fasddf& 
contacts[0].prename=afadfs& 
contacts[0][email protected]& 
contacts[0].contactType=models.constats.ContactType.MANAGER 

只是爲了有更多的信息,我在這裏提供的用戶和聯繫人類

用戶

public class User extends Model{ 
    @Constraints.Required(message = "Field is required") 
    public String identity; 
    public Integer status; 
    @Valid 
    public List<Contact> contacts; 
} 

聯繫

public class Contact extends Generic{ 

    @Constraints.Required(message = "Field is required") 
    public String name; 

    @Constraints.Required(message = "Field is required") 
    public String prename; 

    @Constraints.Required(message = "Field is required") 
    @Constraints.Email 
    public String email; 

    public ContactType contactType; 
} 

ContactType

public enum ContactType { 

    ADMIN,SUPPORT,MANAGER,DEVELOPER,DESIGNER,NO_INFORMATION; 
} 
    public static final Map<String,Object> types=new HashMap<String,Object>() 
    {{ 
     for (ContactType value : ContactType.values()) { 
      String name=value.name().toLowerCase(); 
      name=Character.toUpperCase(name.charAt(0)) + name.substring(1).replaceAll("_", " "); 
      put(ContactType.class.getName() + "."+ value.name(),name); 
     } 
    }}; 
+1

我回答自己,我分享我的結論,以防somobody有同樣的問題:默認情況下,使用**枚舉名**進行綁定。我的發佈方法是錯誤的,因爲它發送了枚舉「models.constants.ContactType.SUPPORT」的完整路徑。正確的是在這種情況下只發送** SUPPORT **。 –

+0

嗨,很好的答案!我唯一的問題是,當我傳入預填表單時,它似乎沒有任何單選按鈕被選中。你有沒有面對同樣的問題? – nbz

+1

這取決於您如何在視圖中實現單選按鈕行爲。在我的情況下,我不使用由Play提供的幫助器,因爲我使用Bootstrap作爲視圖,所以對於檢查部分,我使用代碼'@if(field.value.getOrElse(「」)。equals(「true 「)){checked}' –