2009-06-10 10 views
6

Próbuję zaimplementować coś na pozór bardzo prostego, a ja przez wiele dni walczę z tym w tej kwestii.Ruby on Rails Kraj/Państwo Wybierz Enigma

Moim pożądanym wynikiem końcowym jest lista rozwijana Kraj, powiązana z listą wyboru stanu, w taki sposób, że gdy wybrany jest kraj, stany IF są znane, ALE te stany są wyświetlane w kropli w dół i jeśli dla tego kraju nie są znane stany NIE, zamiast tego wyświetlane jest pole tekstowe.

Czuję, że już prawie jestem. W tym momencie interfejs wygeneruje tę listę stanów na podstawie kraju danej osoby, z tym że odmawia dynamicznej aktualizacji listy rozwijanej.

Część mojego widoku, w którym kraj i stan lokalizacja zbierane wygląda następująco:

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

Częściowa istota mowa w DIV jest w następujący sposób:

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

Wreszcie kod kontrolera, który jest przeznaczony do dynamicznej aktualizacji listy stanów:

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 

Teraz , ten kod jest wywoływany we właściwym czasie i generuje odpowiednie listy stanów. Na przykład, gdy użytkownik kliknie w Australii, "Próba aktualizacji stanów ... Kraj = Australia, stany = Australijskie Terytorium Stołeczne, Nowa Południowa Walia, Terytorium Północne, Queensland, Australia Południowa, Tasmania, Wiktoria, Zachodnia Australia" pojawia się w proces serwera. Jednak nie aktualizuje strony i nie wydrukuje "OK" na końcu. W skrócie linia, która zawodzi jest niewątpliwie

page.replace_html "states_div", 
     :partial => 'states', 
     :object => states, 
     :locals => {:form => form_for(@person)} 

Zauważ, że zastąpienie tej linii z

page.replace_html 'states_div', "<b>is it working</b>" 

właściwie zastępuje div, ale oczywiście nie z niczego użytecznego.

Czy ktoś może mi pomóc zrozumieć, co się tutaj dzieje?

Odpowiedz

1

Wygląda na to, że zakładasz, że zmienna @person jest nadal dostępna w oryginalnym działaniu. Może to być ustawione przez filtr dla bieżącej osoby, ale nie pokazujesz tego w swoim pytaniu.

Jeśli musisz ponownie wyszukać @person, musisz przekazać id w zdalnej_funkcji.

+0

OK, przekazuję identyfikator do funkcji update_states i ponownie sprawdzam osobę. Ale nadal nie aktualizuje formularza dynamicznie. Czy problem polega na tym, że próbuję utworzyć zmienną dla formularza? Innymi słowy, "f = form_form (@object)" jest poprawny w kontrolerze i czy możesz przekazać tę zmienną do częściowej? –

+0

Oczywiście ma to być "f = form_for (@ Object)". –

+1

Czy rzeczywiście otrzymujesz jakiekolwiek błędy z powrotem lub w dziennikach? Możliwe, że nie podoba się form_for w renderowaniu w punkcie_aktualizacji. Może warto spróbować: "wybierz: osoba,: stan ..." zamiast form_do rzeczy. – Shadwell

1

Ryan Bates ma Railscast, który pokazuje, jak wybrać kategorię dla produktu lub utworzyć nową kategorię, wpisując nazwę. To brzmi jak podobny scenariusz do tego, co masz, więc możesz to sprawdzić: Create Model Through Text Field.

+0

Dzięki! Ale nie dokładnie tego, czego szukam. Nie muszę tworzyć nowych stanów na podstawie danych wprowadzanych przez użytkownika; Potrzebuję dynamicznie wypełniać listę wyboru. Teraz, # 88 jest prawie dokładnie tym, co próbuję zrobić, ale nie mogłem uzyskać jego metody pracy z Carmen. Ryan używa modeli State i Country, wydawał mi się bałaganiarski (może mniej bałagan niż mieszanie kodu widoku w kontrolerze, ale jeśli mogę go uruchomić - tj. Z geolokalizacją i wszystkim - planuję rozbić całą lokalizację - gromadzenie mechanizmu w modelu/pomocnika Location). –

0

Zajęło mi to cały dzień, aby dowiedzieć się czegoś, co przynajmniej "zadziała". Używam także Carmen, a także mieszać z tagiem select w form_for formularza modelu (faktycznie, fields_for zagnieżdżone w formula_for ... który dodaje dodatkowe komplikacje).

Myślę, że jest lepsze rozwiązanie, ale to zadziałało. Wybór musi być odwołany przez formularz, ale opcje nie. Tak więc, po raz pierwszy, używam metody state_select Carmen, która zapełnia poprawnie znacznik wyboru i wszystkie znaczniki opcji zagnieżdżonych. Za drugim razem po prostu zastępuję opcje.Spójrz:

W widoku wybrałem użyć metody observe_field ponieważ robię inne rzeczy oprócz aktualizowania stanów (niektóre inne zmiany lokalizacji), ale to powinno działać na remote_function i innych, zbyt:

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

nie należy mylić przez id (user_address_attributes_country) to tylko moje głupie forms_for/fields_for realizacja)

<%= 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' %> 

Wtedy w moim kontrolera, to po prostu wygląda tak:

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 

Uwaga: state_options_for_select jest również z Carmen. Nie mogłem go uruchomić, chyba że umieściłem go wewnątrz bloku respond_to, gdzie domyślam się, że pomocnicy widoku są dostępni. Ponadto, mam twardy kod user_address_attributes_state, który jest moim identyfikatorem zagnieżdżonym wygenerowanym z form_for/fields_for address_form.state_select wywołania renderującego w widoku.

Mam nadzieję, że to pomoże. Jeśli ktokolwiek może to zrobić lepiej, uwierz mi, jestem uszy. Zmienię projekt na czas ... ale potrzebowałem czegoś, co zadziałało dzisiaj i to było najlepsze, co mogłem wymyślić w ograniczonym czasie.