Grails中连接的下拉列表 [英] Connected dropdown lists in Grails

查看:108
本文介绍了Grails中连接的下拉列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的域看起来像这样:

ProductLine hasMany主题有许多子主题。

ProductLine hasMany Topic(s) hasMany Subtopic(s).

On Subtopic create.gsp视图我想要有两个下拉菜单 - 首先选择ProductLine,然后在第二个我想显示属于之前选择的ProductLine的主题。如何实现这个?

On Subtopic create.gsp view I want to have two dropdowns - first for selection of ProductLine, then in the second one I want to show Topics that belong to previously selected ProductLine. How to implement this?

推荐答案

将两个下拉框链接在一起并不难,但是链接三个或更多可能是困难的第一次。下面我链接了三个下拉框,但是您应该可以从这个例子中得出如何将任意数量的下拉框链接在一起。

Chaining two drop down boxes together isn't too hard, but chaining three or more can be difficult the first time. Below I chain three drop-down boxes together, but you should be able to derive from this example how to chain any number of drop-down boxes together.

在我的加载类,当我创建一个新的实例时,我需要知道货物提供者是谁,使用什么货源以及货物是什么。例如,假设我有一个名为ACME Rock的货运提供商。然后想象ACME Rock有两个地点可以从中提供货物,123某某路和456无处路。这些地点将代表货源。最后想象每个货源提供不同的货物。我们可以想象,123某某路只生产摇滚,456无处道路只生产泥土。所有这一切说,这里的创建视图(create.gsp)中的下拉框是我的加载类看起来像。

In my Load class, when I create a new instance, I need to know who the cargo provider was, what cargo source was used, and what the cargo was. For example, imagine I have a cargo provider named ACME Rock. Then imagine ACME Rock has two locations from which they provide cargoes, 123 Somewhere Road, and 456 Nowhere Road. These locations would represent cargo sources. Finally imagine that each cargo source offers different cargoes. We will imagine that 123 Somewhere Road only produces Rock and 456 Nowhere Road only produces Dirt. With all of that said here is what the drop-down boxes in the create view (create.gsp) for my Load class look like.

        <tr class="prop">
            <td valign="top" class="name">
                <label for=cargoProvider"><g:message code="load.cargoProvider.label" default="Cargo Provider"/></label>
            </td>
            <td valign="top" class="value ${hasErrors(bean: loadInstance, field: 'cargoProvider', 'errors')}">
                <g:select from="${cargoProviders}" id="cargoProvider.id" name="cargoProvider.id" noSelection="['':'-Select-']" optionKey="id" optionValue="${{it.businessName?.toString() + ': ' + it?.toString()}}" value="${loadInstance?.cargoProvider?.id}"/>
            </td>
        </tr>

        <tr class="prop">
            <td valign="top" class="name">
                <label for="cargoSource"><g:message code="load.cargoSource.label" default="Cargo Source"/></label>
            </td>
            <td id="cargoSourceCell" valign="top" class=" value ${hasErrors(bean: loadInstance, field: 'cargoSource', 'errors')}">
                <g:select from="${loadInstance?.cargoSource}" id="cargoSource.id" name="cargoSource.id" optionKey="id" value="${loadInstance?.cargoSource?.id}"/>
            </td>
        </tr>

        <tr class="prop">
            <td valign="top" class="name">
                <label for="cargo"><g:message code="load.cargo.label" default="Cargo"/></label>
            </td>
            <td id="cargoCell" valign="top" class="value ${hasErrors(bean: loadInstance, field: 'cargo', 'errors')}">
                <g:select from="${loadInstance?.cargo}" id="cargo.id" name="cargo.id" optionKey="id" value="${loadInstance?.cargo?.id}"/>
            </td>
        </tr>

我们开始链接这些下拉框以及位于同一页面的一些JavaScript(create.gsp )。记住把你的JavaScript放在关闭body元素的< / body> 标签之前。请注意,我使用的是jQuery,而不是Prototype。

We begin chaining these drop-down boxes together with some JavaScript located on the same page (create.gsp). Remember to put your JavaScript right before the </body> tag which closes the body element. Please notice too that I am using jQuery, not Prototype.

<g:javascript>
    $(document).ready(function() {
        $("#cargoProvider\\.id").change(function() {
            var cargoSourceValue = $("#cargoSource\\.id").val();
            $.ajax({
                url: "/truckingmanagement/load/getCargoSources",
                data: "id=" + this.value,
                dataType: 'html',
                cache: false,
                success: function(result) {
                    $("#cargoSourceCell").html(result);
                    $("#cargoSource\\.id").val(cargoSourceValue);
                    $("#cargoSource\\.id").trigger('change');
                }
            });
        });
    });
</g:javascript>

<g:javascript>
    function updateCargoes() {
        var data = ($("#cargoSource\\.id").val() == null) ? "" : $("#cargoSource\\.id").val();
        var cargoValue = $("#cargo\\.id").val();
        $.ajax({
            url: "/truckingmanagement/load/getCargoes",
            data: "id=" + data,
            dataType: 'html',
            cache: false,
            success: function(result) {
                $("#cargoCell").html(result);
                $("#cargo\\.id").val(cargoValue);
            }
        });
    }
</g:javascript>

乍看起来,似乎 updateCargoes 功能没有做任何事情,但实际上是。当在第一个下拉框中进行选择时,第二个下拉框将填充由我的Load控制器中的Grails render 语句生成的HTML。这基本上用新的下拉框替换了原来的下拉框,因此我最初写入下拉框的任何属性都将丢失,除非它们也包含在 render 声明。这就是为什么你看到 getCargoSources 下面的Load控制器的动作,以及正确执行我的应用程序所需的其他属性。您所包含的属性将根据您在视图中要做的具体内容而有所不同,我选择的属性是非常标准的。编写属性两次是一个烦恼,但它比在页面加载时将整个数据集加载到下拉框中的替代方法更好,根据您拥有的数据,可能非常低效的行为。

At first glance it may seem that the updateCargoes function isn't doing anything, but it actually is. When a selection is made in the first drop-down box the second drop-down box is populated with the HTML generated by the Grails render statement in my Load controller. This essentially replaces the original drop-down box with a new one, thus any attributes I had originally written into the drop-down box will be lost unless they are also included in the render statement. That is why you see onchange: 'updateCargoes(); included in the render statement of the getCargoSources action of my Load controller below, as well as other attributes I need for the proper execution of my application. The attributes you include will vary depending on what exactly you want to do in your view and the ones I have picked are pretty standard. Writing the attributes twice is an annoyance, but it is better than the alternative of loading the entire data set into a drop-down box when a page loads, an act that might be very inefficient depending on how much data you have.

def getCargoSources = {
    if(params.id == ""){
        render g.select(name: 'cargoSource.id', onchange: 'updateCargoes(); updateTotal()')
        return
    }

def getCargoes = {
    if(params.id == ""){
        render g.select(name: 'cargo.id', onchange: 'updateTotal()')
        return
    }
    def cargoSource = Address.get(params.id)
    def cargoes = Cargo.findAll("from Cargo as cargoes where cargoes.cargoSource=:cargoSource", [cargoSource: cargoSource])
    render g.select(from: cargoes,  name: 'cargo.id', noSelection: noSelection, onchange: 'updateTotal()', optionKey: 'id')
} 

此时你的链接的下拉框应该正常工作。

At this point your chained drop-down boxes should be working correctly.

这篇关于Grails中连接的下拉列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆