2

我在为枚举对象属性预先选择 HTML 组合框选项时遇到问题。这是我的代码的描述。我有一个包含 CompanyPhone 列表的 Company 模型类:

@Entity
public class Company {
...
    @OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
    public List<CompanyPhone> phones;
...
}

CompanyPhone 有一个 PhoneType 类型的 phoneType 属性,它是枚举:

@Column(name = "PHONE_TYPE")
public PhoneType type;

下面是带有静态 options() 方法的 PhoneType 枚举,用于获取用于在 HTML 模板中显示选择框选项的 Map:

public enum PhoneType {
    @EnumValue("MAI") MAIN,
    @EnumValue("MOB") MOBILE, 
    @EnumValue("FAX") FAX, 
    @EnumValue("CUS") CUSTOM;

    public static Map<String, String> options() {
        LinkedHashMap<String, String> options = new LinkedHashMap<String, String>();
        for (PhoneType v : PhoneType.values()) {
            try {
                EnumValue a = v.getClass().getField(v.name()).getAnnotation(EnumValue.class);
            options.put(a.value(), Messages.get(String.format("%s.%s", 
                    PhoneType.class.getSimpleName(), v.name())));
            } catch (NoSuchFieldException | SecurityException e) { /* ignore */ }
        }
        return options;
    }
}

根据 Ebean 文档,我选择使用 @EnumValue 注释来指定将存储在数据库中的值。我还实现了格式化程序以在 PhoneType 枚举和 String 之间进行转换,并将其注册到根包中 Global.java 的 onStart 方法中:

public class Global extends GlobalSettings {
    @Override
    public void onStart(Application app) {
        Formatters.register(PhoneType.class, new PhoneTypeFormatter());
        ....
    }
    ...
}

这是格式化程序类仅供参考:

public class PhoneTypeFormatter extends SimpleFormatter<PhoneType> {
    @Override
    public PhoneType parse(String input, Locale locale) throws ParseException {
        PhoneType phoneType = null;
        for (PhoneType v : PhoneType.values()) {
            try {
                EnumValue a = v.getClass().getField(v.name()).getAnnotation(EnumValue.class);
                    if (input != null && a != null && input.equals(a.value())) {
                        phoneType = v; 
                        break;
                    }
            } catch (NoSuchFieldException | SecurityException e) { /* ignore */ }
        }
        return phoneType;
    }

    @Override
    public String print(PhoneType phoneType, Locale locale) {
        String v = null;
            try {
                v = (phoneType.getClass().getField(phoneType.name())
                        .getAnnotation(EnumValue.class)).value();
            } catch (NoSuchFieldException | SecurityException e) { /* ignore */     }
            return v;
    }
}

现在,为了显示多部手机的输入字段,我在 HTML 模板文件中使用 Play2 @repeat 指令。这是一个摘录:

...
@phoneGroup(field: Field, className: String = "companyPhone") = {
    <div class="control-group @className">
        <label class="control-label"  for="@field("type").id">@Messages("company.phoneNumbers")</label>
        <div class="controls">
                  <select id="@field("type").id" name="@field("type").name" class="input-small">
            @for((value, text) <- models.PhoneType.options) {
                <option value="@value" 
                  @if(field("type").value != null && value == field("type").value) { selected }>@text</option>
            }
            </select>
            <input type="text" class="inputAreaCode" id="@field("areaCode").id" 
                    name="@field("areaCode").name" value="@field("areaCode").value"
                    placeholder="@Messages("phone.areaCode")">
            <input type="text" class="input-medium" id="@field("number").id" 
                    name="@field("number").name" value="@field("number").value"
                    placeholder="@Messages("phone.number")">
            <a class="removePhone btn btn-danger">@Messages("button.remove")</a>
        </div>
    </div>
}
...
@main {
...
    <div class="companyPhones well">
        @repeat(companyForm("phones"), min = 1) { phone =>
            @phoneGroup(phone)
        }
        @**
         * Keep the hidden block that will be used as template for Javascript copy code.
         **@
        @phoneGroup(
            companyForm("phones[x]"), 
            className = "companyPhone_template") 

        <div class="manage_repeat">
            <a class="addPhone btn btn-success">@Messages("phone.add")</a>
    </div>
    </div>
...
}

到目前为止,一切都很好。当我填写表格并提交数据时,电话号码已正确存储在数据库中。但是当我使用相同的表单编辑现有数据时,组合框中没有选择当前电话类型选项。似乎下面以红色突出显示的@if 指令不起作用。但是没有显示错误:

@phoneGroup(field: Field, className: String = "companyPhone") = {
...
    <select id="@field("type").id" name="@field("type").name" class="input-small">
    @for((value, text) <- models.PhoneType.options) {
        <option value="@value" 
            @if(field("type").value != null && value == field("type").value) { selected }>@text</option>
    }
    </select>
...
}

我尝试在选择之前在 span 元素(以蓝色突出显示)中显示 @field("type").value 的当前值,并且 HTML 页面上的输出值正确,但是未选择 "FAX" 的当前值:

@phoneGroup(field: Field, className: String = "companyPhone") = {
...
    <span>Selected type: @field("type").value</span>
    <select id="@field("type").id" name="@field("type").name" class="input-small">
    @for((value, text) <- models.PhoneType.options) {
        <option value="@value" 
            @if(field("type").value != null && value == field("type").value) { selected }>@text</option>
    }
    </select>
...
}

上面的模板输出以下 HTML:

...
<span>Selected type: FAX</span>
<select id="phones_0__type" name="phones[0].type" class="input-small">
    <option value="MAI">Main</option>
    <option value="MOB">Mobile</option>
    <option value="FAX">Fax</option>
    <option value="CUS">Custom</option>
</select>
...

我被困在这里。我不熟悉 Scala,模板的 Scala 文档对我来说不是很直观。我还尝试显示 @field("type").value 的值而不是 "selected",只是为了好玩,就像这样:

@phoneGroup(field: Field, className: String = "companyPhone") = {
...
    <span>Selected type: @field("type").value</span>
        <select id="@field("type").id" name="@field("type").name" class="input-small">
        @for((value, text) <- models.PhoneType.options) {
            <option value="@value" 
                @if(field("type").value != null) { @field("type").value }>@text</option>
        }
        </select>
 ...
}

它输出正确的值,但小写:

...
<span>Selected type: FAX</span>
<select id="phones_0__type" name="phones[0].type" class="input-small">
    <option value="MAI" fax>Main</option>
    <option value="MOB" fax>Mobile</option>
    <option value="FAX" fax>Fax</option>
    <option value="CUS" fax>Custom</option>
</select>
...

这看起来很奇怪,它在一个地方以大写字母输出,而在另一个地方以小写字母输出。所以,在那之后,另一个尝试只是像这样直接比较一个字符串值:

...
<span>Selected type: @field("type").value</span>
<select id="@field("type").id" name="@field("type").name" class="input-small">
    @for((value, text) <- models.PhoneType.options) {
        <option value="@value" 
        @if(field("type").value != null && "FAX".equals(field("type").value)) { selected  }>@text</option>
    }
</select>

这里仍然没有运气。无论如何,我仍然无法弄清楚如何获得所需的结果,以便在组合框中选择当前值(在本例中为“FAX”)。请问您能否建议如何做到这一点,或者是否有其他替代方法?

任何帮助表示赞赏。谢谢你。

更新 2013-11-06 - 找到适合我的解决方案:

好的,伙计们,在浏览了 Play 源代码树中的 scala/views/helper 文件后,我尝试了在 inputRadioGroup.scala.html 中找到的 if 语句

https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/views/helper/inputRadioGroup.scala.html

因此,我将模板中的 if 语句更改如下:

<select id="@field("type").id" name="@field("type").name" class="input-small">
    @for((value, text) <- models.PhoneType.options) {
        <option value="@value" 
        @if(field("type").value != null && Some(value) == (field("type").value)){ selected }>@text</option>
    }
</select>

因此,使用Some(value)解决了问题,并且现在在组合框中选择了当前选项。我不太明白这意味着什么,我可能需要学习一点 Scala 才能更好地理解模板,但它确实有效。

4

0 回答 0