我的rails应用程序中有一个简单的has_many和belongs_to关系。我正在使用simple_form,并希望根据用户选择的值动态更改下拉选项。
class Processor < ApplicationRecord
has_many :processor_bank_accounts
end
class ProcessorBankAccount < ApplicationRecord
belongs_to :processor
end
<%= simple_form_for [@customer, @transaction] do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :status, :collection => ["payment request"], include_blank: false %>
<%= f.input :processor, collection: @processors ,label_method: :name,value_method: :id,label: "Processor" , include_blank: false %>
<%= f.input :processor_bank_account, collection: @bank_accounts , label_method: :bank_name, value_method: :id, label: "Processor Bank Account" , include_blank: true %>
<%= f.input :tcurrency, collection: @currencies, include_blank: false, label: 'currency' %>
<%= f.input :amount, as: :decimal, label: 'amount' %>
</div>
<div class="form-actions text-center">
<%= f.button :submit, "Add transaction", class: "form-button"%>
</div>
<% end %>
因此,从本质上讲,我需要根据用户选择的处理器来填充processor_bank_account下拉列表。在控制台中,它就是:ProcessorBankAccount.where(processor:processor)。
需要使用JS加载选项,并认为我需要使用JSON,但不确定从何处去
答案 0 :(得分:1)
一种实现方法是使用jQuery对控制器动作进行AJAX调用,然后让Rails通过erb模板处理其余部分。
因此,在您的页面上,通过表单,使用类似以下内容的AJAX调用动作:
<script>
$(document).ready(function() {
$('#processor_id').on('change', function() {
$.ajax({
url: '/transactions/get_processor_bank_accounts',
type: 'GET',
data: {
processor_id: this.value
},
dataType: 'script',
error: function() {
alert('An error occurred retrieving bank accounts for the selected processor.');
}
});
});
});
</script>
注意,#processor_id是下拉控件的ID。
接下来,在您的控制器中通过操作实例化银行帐户:
def get_processor_bank_accounts
@processor_bank_accounts = ProcessorBankAccount.where(processor_id: params[:processor_id])
end
最后简单地创建一个视图,该视图将负责重新填充您的下拉菜单:
$select_list = $('#processor_id');
$select_list.empty();
<% @processor_bank_accounts.each do |pba| %>
$select_list.append($('<option value="<%= pba.id %>"><%= pba.name %></option>'));
<% end %>
答案 1 :(得分:0)
我想出了以下解决方案:
1)向我的处理器控制器添加新方法,以JSON格式呈现第二个(动态)下拉列表的输入:
def processor_bank_accounts
render json: @processor.processor_bank_accounts.each do |bap|
{ id: bap.id, name: bap.name }
end
end
2)将此新功能分配给config / routes中的新路由:
get 'api/bankaccounts', to: 'processors#processor_bank_accounts', as: 'bankaccounts'
3)创建一个JS函数,以使用第一个下拉列表中所选处理器的ID访问路由,并使用JSON数组中的项填充第二个下拉列表:
// select first dropdown
const processor = document.getElementById("transaction_processor");
// select second dropdown
const bapSelect = document.getElementById("transaction_processor_bank_account");
function update_baps(processor_id) {
const url = `INSERTWEBURLHERE/api/bankaccounts?id=${processor_id}`;
fetch(url)
.then(response => response.json())
.then((data) => {
bapSelect.innerHTML = ""; // clear second dropdown
data.forEach((bap) => { // go through all the BAPs
const elem = `<option value="${bap.id}">${bap.bank_name}</option>`; // create option elements to insert into the second dropdown, bank_name is the chosen label method in the form
bapSelect.insertAdjacentHTML("beforeend", elem); // insert options into the dropdown
});
});
}
4)当第一个下拉字段更改时触发JS:
processor.addEventListener('change', function () {
update_baps(parseInt(processor.value));
});
答案 2 :(得分:0)
您应该在选择中添加id
,以便您可以从脚本中识别它们。
$('select#processor').on('change', function() {
var processor_id = this.value;
var processor_bank_account = $('select#processor_bank_account')
$.ajax({
type: "GET",
url: <%= your_path %> ,
data: { processor_id: processor_id },
success: function(data, textStatus, jqXHR){
processor_bank_account.empty();
var option = new Option(data.bank_name, data.id, false, false);
processor_bank_account.append(option);
},
error: function(jqXHR, textStatus, errorThrown){...}
})
});