Ruby on Rails Страна / Штат Выбрать Энигму - PullRequest
6 голосов
/ 10 июня 2009

Я пытаюсь реализовать что-то, казалось бы, очень простое, и я уже несколько дней бьюсь головой об этом.

Мой желаемый конечный результат - это раскрывающийся список Выбор страны, привязанный к раскрывающемуся списку Выбор штата, таким образом, что при выборе данной страны ЕСЛИ известны состояния, ЕСЛИ эти состояния отображаются в раскрывающемся списке выбора. , и если для этой страны не известны никакие состояния, вместо этого отображается текстовое поле.

Я чувствую, что почти там. На этом этапе интерфейс фактически генерирует этот список состояний на основе страны людей, за исключением того, что он отказывается динамически обновлять раскрывающийся список.

Часть моего представления о том, где находится страна и штат, выглядит следующим образом:

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

Теперь этот код вызывается в нужное время и генерирует соответствующие списки состояний. Например, когда пользователь нажимает кнопку «Австралия», в окне появляется сообщение «Попытка обновления штатов ... Страна = Австралия, штаты = Австралийская столичная территория, Новый Южный Уэльс, Северная территория, Квинсленд, Южная Австралия, Тасмания, Виктория, Западная Австралия» серверный процесс. Однако он не обновляет страницу и не выводит «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, но, конечно, ничего полезного.

Может кто-нибудь помочь мне понять, что здесь происходит?

Ответы [ 3 ]

1 голос
/ 10 июня 2009

Похоже, вы предполагаете, что переменная @person все еще доступна из вашего исходного действия. Это может быть установлено фильтром для текущего человека, но вы не показываете это в своем вопросе.

Если вам снова понадобится поиск @person, вам придётся передать идентификатор в своей функции remote_function, я думаю.

1 голос
/ 10 июня 2009

У Райана Бейтса есть Railscast, который показывает, как выбрать категорию для продукта или создать новую категорию, введя имя. Это похоже на сценарий, аналогичный тому, который у вас есть, поэтому вы можете проверить его: Создать модель с помощью текстового поля .

0 голосов
/ 07 декабря 2009

Это заняло у меня целый день, чтобы выяснить, что, по крайней мере, "работает". Я также использую Кармен, а также балуюсь тегом select в форме модели form_for (фактически, fields_for вложен в forms_for ..., что добавляет дополнительные сложности).

Я бы подумал, что есть лучшее решение, но это сработало для меня. Выбор должен ссылаться на форму, а параметры - нет. Таким образом, впервые я использую метод Carmen state_select, который корректно заполняет тег select и все вложенные теги option. Во второй раз я просто заменяю варианты. Взгляните:

В представлении я выбрал использование метода наблюдаемого поля, так как я делаю другие вещи, кроме обновления состояний (некоторые другие изменения локализации), но это должно работать и для remote_function и других:

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

Не смущайтесь идентификатором (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 также от Кармен. Я не смог бы заставить его работать, пока я не поместил его в блок response_to, где, как мне кажется, доступны помощники вида. Кроме того, я жестко код user_address_attributes_state, который является моим вложенным идентификатором, сгенерированным из вызова рендеринга form_for / fields_for address_form.state_select в представлении.

Надеюсь, это поможет. Если кто-то может сделать это лучше, поверьте мне, я весь слух. Я изменю дизайн вовремя ... но мне нужно что-то, что просто сработало сегодня, и это было лучшее, что я мог понять за ограниченное время.

...