Ruby on Rails 国家/州选择 Enigma
我正在尝试实现一些看似非常简单的东西,而且我已经为此绞尽脑汁好几天了。
我想要的最终结果是一个国家/地区选择下拉列表,与一个州/州选择下拉列表相关联,这样当选择给定的国家/地区时,如果州已知,则这些州将显示在选择下拉列表中,并且如果该国家/地区没有已知的州,然后会显示一个文本字段。
我感觉我快到了。 此时,界面实际上会根据人员所在的国家/地区生成州列表,但它拒绝动态更新下拉列表。
我的视图中收集国家和州位置的部分如下所示:
# _person_setup.html.erb
<td>
<%= f.label :country, 'Select your country' %>*<br />
<%= f.select :country, Carmen::country_names, {},
{:style => 'width: 200px',
:id => 'country_select',
:onchange => remote_function(
:url => {:action => 'update_states'},
:with => "'country='+value")} %>
</td><td>
<p>
<div id="states_div">
<%= render :partial => 'states',
:object => Carmen::states(
Carmen::country_code(
@person.country)),
:locals => {:form => f} %>
</div>
</p>
</td>
DIV 中引用的部分如下:
# _states.html.erb
<% unless states.nil? or states.empty? %>
<%= form.label :state, 'Select your state' %>*<br />
<%= form.select :state, states.collect{|s| [s[0], s[0]]} %>
<% else %>
<%= form.label :state, 'Please enter state or province' %>*<br />
<%= form.text_field :state %>
<% end %>
最后,旨在动态更新州列表的控制器代码:
def update_states
puts "Attempting to update states..."
q = params[:country]
states = Carmen::states(Carmen::country_code(q))
puts "Country = #{q}, states = #{states.collect{|s| s[0]}.join(", ")}."
render :update do |page|
page.replace_html "states_div",
:partial => 'states',
:object => states,
:locals => {:form => form_for(@person)}
end
puts "OK"
end
现在,正在调用此代码适当的时间并生成适当的状态列表。 例如,当用户单击澳大利亚时,“尝试更新州...国家=澳大利亚,州=澳大利亚首都领地、新南威尔士州、北领地、昆士兰州、南澳大利亚州、塔斯马尼亚州、维多利亚州、西澳大利亚州”显示在服务器进程。 但是它不会更新页面,也不会在最后打印“确定”。 简而言之,失败的行无疑是
page.replace_html "states_div",
:partial => 'states',
:object => states,
:locals => {:form => form_for(@person)}
注意,用适当的方式替换该行
page.replace_html 'states_div', "<b>is it working</b>"
可以替换 div,但当然不是用任何有用的东西。
有人可以帮助我理解这里发生了什么吗?
I am trying to implement something seemingly very simple, and I have been beating my head against it for days at this point.
My desired end result is a Country select drop-down, tied to a State select drop-down, in such a way that when a given country is selected, IF states are known THEN those states are displayed in a select drop down, and if NO states are known for that country, then a text field is displayed instead.
I feel like I am almost there. At this point the interface will actually generate that list of states based on the persons' country, except it is refusing to update the drop-down dynamically.
The portion of my view where country and state location is gathered looks like:
# _person_setup.html.erb
<td>
<%= f.label :country, 'Select your country' %>*<br />
<%= f.select :country, Carmen::country_names, {},
{:style => 'width: 200px',
:id => 'country_select',
:onchange => remote_function(
:url => {:action => 'update_states'},
:with => "'country='+value")} %>
</td><td>
<p>
<div id="states_div">
<%= render :partial => 'states',
:object => Carmen::states(
Carmen::country_code(
@person.country)),
:locals => {:form => f} %>
</div>
</p>
</td>
The partial being referenced in the DIV is as follows:
# _states.html.erb
<% unless states.nil? or states.empty? %>
<%= form.label :state, 'Select your state' %>*<br />
<%= form.select :state, states.collect{|s| [s[0], s[0]]} %>
<% else %>
<%= form.label :state, 'Please enter state or province' %>*<br />
<%= form.text_field :state %>
<% end %>
Finally, the controller code which is intended to update the list of states dynamically:
def update_states
puts "Attempting to update states..."
q = params[:country]
states = Carmen::states(Carmen::country_code(q))
puts "Country = #{q}, states = #{states.collect{|s| s[0]}.join(", ")}."
render :update do |page|
page.replace_html "states_div",
:partial => 'states',
:object => states,
:locals => {:form => form_for(@person)}
end
puts "OK"
end
Now, this code is being called at the proper time and generating the appropriate lists of states. For example, when the user clicks Australia, "Attempting to update states... Country = Australia, states = Australian Capital Territory, New South Wales, Northern Territory, Queensland, South Australia, Tasmania, Victoria, Western Australia" shows up in the server process. However it doesn't update the page, and won't print the "OK" at the end. In short the line which is failing is undoubtedly
page.replace_html "states_div",
:partial => 'states',
:object => states,
:locals => {:form => form_for(@person)}
Note that replacing this line with
page.replace_html 'states_div', "<b>is it working</b>"
properly replaces the div, but of course not with anything useful.
Can someone help me understand what is going on here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
看起来您假设 @person 变量仍然可以从您的原始操作中获得。 这可以通过当前人员的过滤器来设置,但您不会在问题中显示这一点。
如果您确实需要再次查找@person,我认为您必须在remote_function 中传递id。
It looks like you're assuming that the @person variable is still available from your original action. This could be set up by a filter for the current person but you don't show that in your question.
If you do need to lookup the @person again you'll have to pass the id through in your remote_function I think.
Ryan Bates 有一个 Railscast,它展示了如何为产品选择类别或通过键入名称创建新类别。 这听起来与您所遇到的情况类似,因此您可能需要检查一下:通过文本字段创建模型。
Ryan Bates has a Railscast that shows how to select a category for a product or create a new category by typing the name. It sounds like a similar scenario to what you have, so you might want to check it out: Create Model Through Text Field.
这花了我一整天的时间来找出至少可以“工作”的东西。 我还在使用 Carmen,并且还弄乱了 form_for 模型表单中的 select 标签(实际上, fields_for 嵌套在 forms_for 中......这增加了额外的复杂性)。
我认为有更好的解决方案,但这对我有用。 选择需要由表单引用,但选项不需要。 因此,第一次,我使用 Carmen state_select 方法正确填充选择标签和所有嵌套选项标签。 第二次,我只是更换了选项。 看一下:
在视图中,我选择使用observe_field方法,因为除了更新状态(其他一些本地化更改)之外,我还执行其他操作,但这也应该适用于remote_function和其他方法:
不要被id混淆( user_address_attributes_country)这只是我愚蠢的 forms_for/fields_for 实现)
然后在我的控制器中,它看起来像这样:
注意:
state_options_for_select
也来自 Carmen。 我无法让它工作,除非我把它放在 respond_to 块中,我猜视图助手是可用的。 另外,我硬编码了user_address_attributes_state
这是我从视图中的 form_for/fields_for address_form.state_select 渲染调用生成的嵌套 id。我希望这有帮助。 如果有人能做得更好,请相信我,我洗耳恭听。 我会及时更改设计......但需要一些今天就可以使用的东西,这是我在有限的时间内能想到的最好的。
This took me a full day to figure out something that would at least "work". I am also using Carmen and also messing with the select tag in a form_for model form (actually, fields_for nested within forms_for...which adds additional complications).
I would think there is a better solution but this worked for me. The select needs to be referenced by the form but the options don't. Thus, first time through, I use the Carmen state_select method which populates the select tag correctly and all the nested options tags. The second time through, I just replace the options. Take a look:
In the view, I chose to use an observe_field method since I do other things besides update the states (some other localization changes) but this should work for remote_function and others, too:
Don't be confused by the id (user_address_attributes_country) it is just my silly forms_for/fields_for implementation)
Then in my controller, it just looks like this:
Note:
state_options_for_select
is also from Carmen. I could not get it to work unless I put it inside the respond_to block where I guess the view helpers are available. Also, I hard codeuser_address_attributes_state
which is my nested id generated from the form_for/fields_for address_form.state_select rendering call in the view.I hope this helps. If anyone can do it better, believe me, I'm all ears. I'll change the design in time...but needed something that just worked today and this was the best I could figure out in a limited time.