ruby-on-rails - 在 Rails 中使用 js.erb
问题描述
在带有 的 Rails 5 应用程序中devise
,我需要使用一个new.js.erb
文件来更新我的注册视图和控制器中的选择标签。我似乎无法弄清楚为什么我的new.js.erb
文件不起作用。
我尝试respond_to
在控制器中使用如下,
注册-controller.rb
def new
super
@cities = CS.get(:us,params[:state])
respond_to do |format|
format.js { render '/new.js.erb' }# layout: false }
format.html
end
end
新的.html.erb
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), :remote => true) do |f| %>
<div class="signup-input-container">
<div class="field">
<%= f.text_field :firstname, autofocus: true, autocomplete: "firstname", placeholder: "First name", class: "signup-input-container--input" %>
</div>
<div class="field">
<%= f.select :state, options_for_select(CS.states(:us).map { |code, name| [name, code] }),{:prompt => "State"}, {:class => "signup-input-container--input", :id => "state-picker"} %>
</div>
<div class="field">
<%= f.select :city, options_for_select([]),{}, {:class => "signup-input-container--input", :id => "city-picker"} %>
</div>
</div>
<% end %>
新的.js.erb
var city = document.getElementById("city-picker");
while (city.firstChild) city.removeChild(city.firstChild);
var placeholder = document.createElement("option");
placeholder.text = "Choose a city";
placeholder.value = "";
city.appendChild(placeholder);
<% @cities.each do |c| %>
city.options[city.options.length] = new Option('<%= c %>');
<% end %>
main.js
var state = document.getElementById("state-picker");
state.addEventListener("change", function() {
$.ajax({
url: "/states?state=" + state.value,
type: "GET"
})
})
我希望这会在我的控制器中使用我的城市数组创建选择标签选项。有谁知道如何让它工作?
解决方案
为了解决这个问题,您应该设置一个单独的控制器,您可以在其中异步获取数据,或者还有几个免费的 API 可用于地理查找,例如Googles Geocoding API和Geonames。
要设置单独的控制器,您可以通过以下方式进行:
# /config/routes.rb
get '/states/:state_id/cities', to: 'cities#index'
# /app/controllers/cities_controller.rb
class CitiesController < ApplicationController
# GET
def index
@cities = CS.get(:us, params[:state_id])
respond_to do |f|
f.json { render json: @cities }
end
end
end
我会完全跳过使用.js.erb
模板,只返回 JSON 数据,您可以直接在 JS 中使用或与许多现有的自动完成解决方案之一一起使用。.js.erb
仅对您想要重用服务器端模板的大量 HTML 模板(例如渲染整个表单)有意义 - 它大大增加了复杂性,并且通常会使您的 javascript 变得一团糟,仅仅输出一个列表是不值得的选项标签。
// If you are using jQuery you might as well setup a delegated
// handler that works with turbolinks,
$(document).on('change', '#state-picker', function(){
$.getJSON("/states/" + $(this).value() + "/cities", function(data){
// using a fragment avoids updating the DOM for every iteration.
var $frag = $('<select>');
$.each(data, function(city){
$frag.append$('<option>' + data + '</option>');
});
$('#city-picker').empty()
.append($('frag').children('option'));
});
});
推荐阅读
- android - 在 Jetpack Compose 中的 viewModel 问题中列出搜索
- javascript - 在 javascript 中使用 map 更改对象数组
- python - 如何在 Python 中将奇数拆分为多个部分(密码生成器项目)
- sftp - Mule 4:SFTP 连接器在 CloudHub 中失去连接并出现管道关闭错误
- postgresql - 如何在postgresql的字符串中获取特定字符串
- excel - excel vba找不到打开的工作簿
- hierarchical-clustering - HAC:树状图中的儿童
- excel - 我可以将 10 个 TextBox_Change() 订阅减少到一个吗?
- html - 是否可以设置 Mat-Checkbox 样式以显示 X 而不是复选标记?
- mysql - 使用 cron [Scheduler] QueryFailedError: read ECONNRESET 时出现错误