如何从具有相同名称的挂毯文本字段中获取数据?

How to get data from tapestry textfield with the same name?

我对挂毯很陌生, 我在使用它时遇到了几个问题,如何从同名的挂毯文本字段中获取值?

例如:

<t:form t:id="names">
    <t:errors/>
    <div class="input-box">
        <t:textfield type="text" name="birthdate[Day]"/>
        <t:textfield type="text" name="birthdate[Month]"/>
        <t:textfield type="text"  name="birthdate[Year]"/>
    </div>
    <div class="input-box">
        <div class="col-md-12">
            <input type="submit" name="proceed" class="btn" value="Proceed" />
        </div>
    </div>
</t:form>

我尝试用生日[日] = 20、生日[月] = 08、生日[年] = 1992 填充它,然后像这样在后端调试它:

@Property
@Persist(PersistenceConstants.FLASH)
private List<String> birthdate;

Object onSuccess() {
    logger.info("data birthdate:            "+birthdate);  // print null
    logger.info("data birthdate toString:   "+birthdate.toString());  // print null
    logger.info("data birthdate 0:          "+birthdate.get(0));  // print null

    return null;
}

全部只返回null..

如何解决?

提前致谢

来自 Spring 和 Hibernate 时代,Tapestry 感觉很奇怪。根据我 10 分钟的阅读时间,您没有正确映射字段并且遗漏了一些内容,例如

  • 您没有使用 t:id
  • 您的 .tml 中有 3 个文本字段,然后 .java 中有一个列表,不确定您打算在那里做什么

作为示例,我做了如下操作 Names.java

package com.raf.test.pages;

import java.util.Date;

import org.apache.tapestry5.PersistenceConstants;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.slf4j.Logger;

public class Names {
    @Inject
    private Logger logger;

    @Property
    @Persist(PersistenceConstants.FLASH)
    private String birthDay;

    @Property
    @Persist(PersistenceConstants.FLASH)
    private String birthMonth;

    @Property
    @Persist(PersistenceConstants.FLASH)
    private String birthYear;

    @Property
    @Persist(PersistenceConstants.FLASH)
    private String aDate;

    @Property
    @Persist(PersistenceConstants.FLASH)
    private String monthAndYear;

    @Property
    @Persist(PersistenceConstants.FLASH)
    private Date actualDateField;

    Object onSuccess() {
       logger.info("birthDay: " + birthDay);
       logger.info("birthMonth: " + birthMonth);
       logger.info("birthYear: " + birthYear);

       if(aDate != null && !aDate.isEmpty()) {
           String[] chunks = aDate.split("-");
           if(chunks.length > 2) {
               logger.info("aDate [Year]: " + chunks[0]);
               logger.info("aDate [Month]: " + chunks[1]);
               logger.info("aDate [Day]: " + chunks[2]);
           }
       }

       logger.info("monthAndYear: " + monthAndYear);

       logger.info("actualDateField: " + actualDateField);

       return null;
    }
}

Names.tml 如下

<html t:type="layout" title="test com.example"
      xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
      xmlns:p="tapestry:parameter">

<t:form t:id="names">
    <t:errors/>
    <div class="input-box">
        <t:textfield type="text" name="birthdate[Day]" placeholder="birthdate[Day]" t:id="birthDay"/>
        <t:textfield type="text" name="birthdate[Month]" placeholder="birthdate[Month]" t:id="birthMonth"/>
        <t:textfield type="text"  name="birthdate[Year]" placeholder="birthdate[Year]" t:id="birthYear"/>
        <!-- Uses html5 date type-->
        <t:textfield type="date"  name="normladate" placeholder="Normal date" t:id="aDate"/>

        <!-- Uses html5 month -->
        <t:textfield type="month"  name="justmonth" placeholder="Month Year" t:id="monthAndYear"/>

        <!-- Actual date field -->
        <t:datefield  name="actualDateField" placeholder="Actual date" t:id="actualDateField"/>
    </div>
    <div class="input-box">
        <div class="col-md-12">
            <input type="submit" name="proceed" class="btn" value="Proceed" />
        </div>
    </div>
</t:form>
</html>

这里是 eclipse 中的示例输出

[INFO] pages.Names birthDay: bb
[INFO] pages.Names birthMonth: aa
[INFO] pages.Names birthYear: 2nineteen
[INFO] pages.Names aDate [Year]: 2018
[INFO] pages.Names aDate [Month]: 02
[INFO] pages.Names aDate [Day]: 18
[INFO] pages.Names monthAndYear: 2018-02
[INFO] pages.Names actualDateField: Fri Feb 16 00:00:00 EST 2018

如您所见,Names.tml 中的每个字段都映射到 Names.java POJO 中的相应字段。

您似乎认为 Tapestry 的 TextField 是 与 HTML "input type=text" HTML 元素相同的东西。它不是。 TextField 是一个 Tapestry 组件,它 输出 一个 "input type=text" HTML 元素,但它使用 "value" 参数而不是 [=48] 标识正在编辑的对象=],如文档中所述:http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/TextField.html

我提供了 3 种可能的方法:

1) 如果可能,不要对日期部分使用 3 元素列表。这只会让一切变得更难、更混乱。相反,每个都有一个单独的 属性,称为 birthDay、birthMonth 和 birthYear:

@Property
@Persist(PersistenceConstants.FLASH)
private String birthDay, birthMonth, birthYear;

在您的模板中添加以下内容:

<t:textfield t:id="birthDay" value="birthDay"/>
<t:textfield t:id="birthMonth" value="birthMonth"/>
<t:textfield t:id="birthYear" value="birthYear"/>

或者在您的模板中使用以下内容,这是等效的(因为如果 Tapestry 没有找到值参数,它会查找与 t:id 参数匹配的 属性 )并且更简洁:

<t:textfield t:id="birthDay"/>
<t:textfield t:id="birthMonth"/>
<t:textfield t:id="birthYear"/>

2) 或者,如果您真的想让您的网页设计师对每个字段使用相同的 "name" 属性,那么您可以这样写,等价于:

<input type="text" t:type="textfield t:id="birthDay" name="birthday"/>
<input type="text" t:type="textfield t:id="birthMonth" name="birthday"/>
<input type="text" t:type="textfield t:id="birthYear" name="birthday"/>

(如果您确实在 Tapestry 组件上添加了 "name" 参数,那么它的值将被忽略并且 而不是 出现在结果 HTML 中。相反,TextField 发出的 HTML(通常)包含一个名称属性,其值与 t:id 属性匹配。)

3) 最后,您 可以 完全跳过 TextField 组件,只使用普通的旧 HTML 表单元素和您的 3 元素字符串列表:

<input type="text" name="birthday" value="${birthdate.get(0)}"/>
<input type="text" name="birthday" value="${birthdate.get(1)}"/>
<input type="text" name="birthday" value="${birthdate.get(2)}"/>

然后您可以使用以下方法检索提交的值:

@Inject
private Request request;
...
String[] birthDateParts = request.getParameters("birthday");
birthdate = Arrays.asList(birthDateParts);

这很尴尬。而且您会失去 Tapestry 的所有有用的验证和错误报告功能,并且您必须自己管理所有细节。所以我不推荐这条路线。