在 Tapestry 5.3 中链接多个 select 组件(Ajax 更新)

Chaining multiple select components in Tapestry 5.3 (Ajax update)

我正在使用 Tapestry 5.3.7,我想使用 Ajax 链接 select 表单元素:如果我在 select 元素中选择一个选项,另一个 select 似乎根据您的第一选择选择另一个元素。我尝试了挂毯文档中的示例,并针对我的项目进行了调整。尽管我的自定义代码非常接近示例,但我总是有以下错误:

Render queue error in SetupRender[SelectZoneDemo:version]: Component SelectZoneDemo:version must be enclosed by a Form component.

来自文档的工作示例(select 组件 CarMaker 的链接) http://tapestry.apache.org/5.3/apidocs/org/apache/tapestry5/corelib/components/Select.html)

这是我的代码: 模板文件 (.tml)

<t:form>
    <p>
        <t:errors />
    </p>
    <p>
        <t:select t:id="selectApplicatifs" t:model="selectApplicatifs"
            t:value="selectedApplicatif" validate="required" zone= "VersionZone"
            t:zone="versionZone" t:encoder="ApplicatifDtoEncoder" />
    </p>

    <t:zone t:id="versionZone" id="versionZone">
        <t:if test="selectedApplicatif">
            <p>
                <t:select t:id="version" model="selectVersions" t:encoder="VersionDtoEncoder" />
            </p>
        </t:if>
        <p>
            <t:submit value="literal:Submit" />
        </p>
    </t:zone>

</t:form>

Java 文件

    @Inject
    private AjaxResponseRenderer ajaxResponseRenderer;

    @Inject
    private IServiceApplicatif serviceApplicatif;

    @Inject
    private SelectModelFactory selectModelFactory;

    @Property
    @Persist
    private SelectModel selectApplicatifs;

    @Property
    @Persist
    private String version;

    @Property
    @Persist
    private SelectModel selectVersions;

    @Inject
    @Property
    private ApplicatifDtoEncoder applicatifDtoEncoder;

    @Inject
    @Property
    private VersionDtoEncoder versionDtoEncoder;

    @Property
    @Persist
    private ApplicatifDto selectedApplicatif;

    @InjectComponent
    private Zone versionZone;

    public void onActivate() {
        List<ApplicatifDto> listApplicatifs = serviceApplicatif.findAllApplicatifDto();
        List<VersionDto> listVersionApplicatifs = new ArrayList<VersionDto>();
        selectApplicatifs = selectModelFactory.create(listApplicatifs, "nom");
        if (selectVersions == null) {
            selectVersions =   selectModelFactory.create(listVersionApplicatifs,"version");
        }
    }

    public void onValueChangedFromSelectApplicatifs(ApplicatifDto applicatifDto) {

        List<VersionDto> versionList = applicatifDto.getVersionList();
        selectVersions = selectModelFactory.create(versionList,"version");

        ajaxResponseRenderer.addRender(versionZone);
    }

如您所见,通过 ajax 在表单中呈现区域可能会变得棘手。字段需要 FormSupport instance to be on the Environment 堆栈。这通常在父表单呈现时添加到环境中,但正如您所发现的,在呈现表单内的区域时,FormSupport 不可用。

这里有几个选项:

  1. 有一个区域包裹整个表单并通过 ajax
  2. 更新整个表单
  3. 不刷新区域,而是使用 javascript(通过 JavaScriptSupport)更新现有 select 菜单中的选项
  4. 使用 Observe mixin 更新表单中的区域。您可以渲染自己的 select,而不是使用核心挂毯 select 组件。这可能需要您在最终提交表单时使用@RequestParameter 来获取服务器端的值。
  5. 使用FormInjector。我自己从未使用过它,但我认为它以某种方式欺骗了环境。我不确定您如何在活动中传递用户的 selection。我认为这个组件可能在 Tapestry 5.4 中也被废弃了。