Объединение двух выпадающих списков не так уж сложно, но объединение трех и более может быть трудным в первый раз.Ниже я объединяю три раскрывающихся списка, но вы сможете извлечь из этого примера, как объединить любое количество раскрывающихся списков.
В моем классе Load
, когда я создаю новыйНапример, мне нужно знать, кем был поставщик грузов, какой источник груза использовался и каким был груз.Например, представьте, у меня есть провайдер грузов по имени ACME Rock.Затем представьте, что у ACME Rock есть два места, откуда они доставляют грузы: 123 Somewhere Road и 456 Nowhere Road.Эти места будут представлять источники груза.Наконец, представьте, что каждый источник груза предлагает разные грузы.Мы представим, что 123 Somewhere Road производит только Rock, а 456 Nowhere Road - только Dirt.С учетом всего вышесказанного, вот как выглядят раскрывающиеся окна в представлении создания (create.gsp) для моего Load
класса.
<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.
<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
ничего не делает, но на самом деле это так.Когда выбор сделан в первом раскрывающемся списке, второй раскрывающийся список заполняется HTML-кодом, сгенерированным оператором Grails render
в моем контроллере загрузки.Это по существу заменяет исходный раскрывающийся список новым, поэтому любые атрибуты, которые я первоначально записал в раскрывающийся список, будут потеряны, если они также не включены в оператор render
.Вот почему вы видите onchange: 'updateCargoes();
, включенный в оператор render
действия getCargoSources
моего контроллера загрузки ниже, а также другие атрибуты, которые мне нужны для правильного выполнения моего приложения.Атрибуты, которые вы включаете, будут различаться в зависимости от того, что именно вы хотите сделать в своем представлении, и те, которые я выбрал, довольно стандартны.Написание атрибутов дважды раздражает, но это лучше, чем альтернатива загрузки всего набора данных в раскрывающееся окно при загрузке страницы, что может быть очень неэффективно в зависимости от объема данных.
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')
}
На этом этапе ваши выпадающие списки должны работать правильно.