#javascript #grails #drop-down-menu
#javascript #grails #выпадающее меню
Вопрос:
Мой домен выглядит примерно так:
В продуктовой строке есть множество тем и подтем.
В представлении Subtemic create.gsp я хочу иметь два выпадающих списка — первый для выбора продуктовой линейки, затем во втором я хочу показать темы, которые принадлежат к ранее выбранной продуктовой линейке. Как это реализовать?
Ответ №1:
Объединить два выпадающих списка вместе не так уж сложно, но связать три или более в цепочку может быть сложно в первый раз. Ниже я объединяю три выпадающих списка вместе, но вы должны быть в состоянии извлечь из этого примера, как объединить любое количество выпадающих списков вместе.
В моем Load
классе, когда я создаю новый экземпляр, мне нужно знать, кто был поставщиком груза, какой источник груза использовался и что это был за груз. Например, представьте, что у меня есть поставщик грузовых перевозок с именем ACME Rock. Тогда представьте, что у ACME Rock есть два местоположения, из которых они доставляют грузы, 123 Somewhere Road и 456 Nowhere Road. Эти местоположения будут представлять источники груза. Наконец, представьте, что каждый источник грузов предлагает разные грузы. Мы представим, что 123 Где-то дорога производит только камень, а 456 Нигде дорога производит только грязь. Учитывая все сказанное, вот как выглядят выпадающие списки в представлении создания (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')
}
На этом этапе ваши связанные выпадающие списки должны работать правильно.
Комментарии:
1. у меня не было TD для создания дампа html, который я просто хотел перезаписать или обновить из результата в моем текущем выпадающем списке?
2. @danielad Извините, но я не понимаю, о чем вы говорите.
Ответ №2:
Комментарии:
1. Пожалуйста, смотрите Действительно ли ответы, которые содержат ссылки в другом месте, действительно «хорошие ответы»?