2011-11-11 44 views
1

我的域看起来是这样的:Grails中的已连接下拉列表

ProductLine hasMany Topic(s)hasMany Subtopic(s)。

关于Subtopic create.gsp视图我想要有两个下拉列表 - 第一个用于选择ProductLine,然后在第二个下拉列表中显示属于先前选择的ProductLine的主题。如何实现这一点?

回答

2

链接两个下拉框起来不是太难,但链接三个或更多的可能是困难的第一次。下面我将三个下拉框链接在一起,但您应该能够从此示例中获得如何将任意数量的下拉框链接在一起。

在我的Load课程中,当我创建一个新实例时,我需要知道货运商是谁,货源是什么以及货物是什么。例如,假设我有一个名叫ACME Rock的货运商。那么想象一下,ACME Rock有两个地方可以提供货物,123 Somewhere Road和456 Nowhere Road。这些地点将代表货物来源。最后想象一下,每个货源都提供不同的货物。我们会想象,123 Somewhere Road只会产生Rock和456 Nowhere Road只会产生污垢。这里所说的全部就是我的Load类的创建视图(create.gsp)中的下拉框。

 <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)上一起链接这些下拉框。请记住在关闭body元素的</body>标记之前放置JavaScript。请注意,我正在使用jQuery,而不是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语句中。这就是为什么你看到onchange: 'updateCargoes();包含在我的Load控制器的getCargoSources动作的render声明中,以及我需要的其他属性,以便正确执行我的应用程序。你所包含的属性会根据你想要在视图中做什么而变化,而我选择的属性是非常标准的。两次写入属性是一件令人烦恼的事情,但它比在加载页面时将整个数据集加载到下拉框中的替代方法要好,这种行为可能非常低效,具体取决于您拥有的数据量。

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') 
} 

在这一点上你的链式下拉框应该正常工作。

+0

你应该得到更多的信贷:)不错的工作! YYYYYYYYYYYYYYY – danielad

+0

我没有TD转储的HTML我简单地想覆盖或更新我的当前下拉框从结果? – danielad

+0

@danielad对不起,但我不明白你在说什么。 – ubiquibacon