【问题标题】:Ruby on Rails Country/State Select EnigmaRuby on Rails 国家/地区选择谜
【发布时间】:2010-11-01 20:21:30
【问题描述】:

我正在尝试实现一些看似非常简单的东西,而这几天我一直在努力解决它。

我的期望的最终结果是一个国家选择下拉,绑定到状态选择下拉,以这样的方式,即选择给定的国家/地区时,如果状态是已知的,则在“选择”下拉“中将显示这些状态,并且如果该国家/地区没有已知的州,则会显示一个文本字段。

我觉得我快到了。此时,界面实际上将根据人员的国家/地区生成该状态列表,但它拒绝动态更新下拉列表。

收集国家和州位置的视图部分如下所示:

# _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

现在,该代码在适当的时间被调用并生成适当的状态列表。例如,当用户单击澳大利亚时,“正在尝试更新州... Country = Australia, states = Australian Capital Territory, New South Wales, Northern Territory, Queensland, South Australia, Tasmania, Victoria, Western Australia”会显示在服务器进程。但是它不会更新页面,也不会在最后打印“OK”。简而言之,失败的路线无疑是

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,但当然不是用任何有用的东西。

谁能帮我理解这里发生了什么?

【问题讨论】:

    标签: ruby-on-rails ruby ajax rjs


    【解决方案1】:

    Ryan Bates 有一个 Railscast,它展示了如何为产品选择类别或通过键入名称来创建新类别。这听起来与您所拥有的情况相似,因此您可能想查看一下:Create Model Through Text Field

    【讨论】:

    • 谢谢!但不完全是我想要的。我不需要根据用户输入创建新状态;我只需要动态填充一个选择列表。现在,#88 几乎正是我想要做的,但我无法让他的方法与 Carmen 一起工作。 Ryan 使用 State 和 Country 模型,这对我来说似乎很混乱(可能不如在控制器中混合视图代码那么混乱,但如果我能让它工作——即,使用地理位置和一切——我打算打破整个位置 -将机制收集到位置模型/助手中。)
    【解决方案2】:

    您似乎假设 @person 变量仍可从您的原始操作中使用。这可以通过针对当前人员的过滤器进行设置,但您没有在问题中显示。

    如果您确实需要再次查找@person,我认为您必须在 remote_function 中传递 id。

    【讨论】:

    • 好的,我将 id 传递给 update_states 函数并再次查找此人。但它仍然没有动态更新表单。是我试图为表单创建变量的问题吗?换句话说,“f = form_form(@object)”在控制器中是否有效,你能把这个变量传递给部分吗?
    • 您实际上是否收到任何错误或日志中的错误?它可能不喜欢 update_states 中渲染的 form_for。可能值得尝试:“select :person, :state ...”而不是 form_for 的东西。
    • 好的,就是这样。你不能从控制器创建这样的表单范围——你也不应该这样做。一旦我将这个人传递给部分并从那里创建一个新的表单范围,它就开始工作了。谢谢,沙德。
    【解决方案3】:

    这花了我一整天的时间来找出至少“有效”的东西。我也在使用 Carmen 并且还弄乱了 form_for 模型表单中的 select 标记(实际上,fields_for 嵌套在 forms_for 中......这增加了额外的复杂性)。

    我认为有更好的解决方案,但这对我有用。选择需要被表单引用,但选项不需要。因此,第一次通过时,我使用了 Carmen state_select 方法,该方法正确填充了 select 标签和所有嵌套的 options 标签。第二次通过,我只是替换选项。看看:

    在视图中,我选择使用observe_field 方法,因为除了更新状态(一些其他本地化更改)之外,我还做了其他事情,但这也适用于remote_function 和其他:

    <%= address_form.country_select :country, {:prompt => "--Select One--"} %>
    

    不要被 id (user_address_attributes_country) 弄糊涂了,这只是我愚蠢的 forms_for/fields_for 实现)

    <%= observe_field :user_address_attributes_country, :url => { :action => :changecountry }, :with => 'new_country' %>
    
    <%= address_form.state_select :state, @user.address.country, {:prompt => "--Select One--"}, :style => 'width: 90px' %>
    

    然后在我的控制器中,它看起来像这样:

    def changecountry
      c = params[:new_country]
    
      respond_to do |format|
        format.html
        format.js {
          render :update do |page|
            page['user_address_attributes_state'].innerHTML = \
              "<option>--Select One--</option>" + state_options_for_select(nil, c)
          end
        }
      end
    end
    

    注意:state_options_for_select 也来自 Carmen。除非我把它放在我猜视图助手可用的 respond_to 块中,否则我无法让它工作。另外,我对user_address_attributes_state 进行了硬编码,这是我从视图中的 form_for/fields_for address_form.state_select 渲染调用生成的嵌套 id。

    我希望这会有所帮助。如果有人能做得更好,相信我,我全神贯注。我会及时更改设计......但需要一些今天刚刚工作的东西,这是我能在有限的时间内找到的最好的东西。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-16
      • 1970-01-01
      • 2015-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-27
      相关资源
      最近更新 更多