Di recente ho dovuto implementare in una view la classica ricerca con due select dipendenti l’una dall’altra. Volevo però lasciare il template .erb il più possibile pulito e rendere il codice che carica le option della select figlia il più possibile riutilizzabile e generico.
Supponiamo dunque di avere due modelli, SpecializationType e Specialization, così composti:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
class SpecializationType < ActiveRecord::Base |
Come si puo’ notare, Specialization dipende dalla SpecializationType che andremo a selezionare.
Nel nostro template, creeremo le due dropdown in questo modo:
1 2 3 4 5 6 7 8 9 10 11 |
<%= form_tag users_path, {:method => :get, :class => "users_search_form"} do %> |
Come si puo’ notare, la dropdown figlia indica in una serie di “data-option” tutto il necessario per poter caricarsi a runtime gli elementi.
In particolare:
“data-option-dependent” => true, indica che questa dropdown dipende da una dropdown padre
“data-option-observed” => “specialization_type_id”, specifica l’id della dropdown da monitorare. Il suo cambio di valore scatenerà la richiesta al server
“data-option-url” => “/specialization_type/:specialization_type_id:/specializations.json”, è l’url che andrò a chiamare sul server. Lo script andrà a sostituire :specialization_type_id: con l’id dell’elemento selezionato nella dropdown padre
“data-option-key-method” => :id, indica che userò il campo ID del json tornato dal server come attrbuto “chiave” della < option >
“data-option-value-method” => :name, indica che userò il campo NAME del json tornato dal server come attrbuto “valore” della < option >
Aggiungiamo poi in application.js il seguente codice per gestire tutte le dropdown dipendenti:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
jQuery(document).ready(function () { |
Basterà ora definire nel file routes.rb la seguente rotta:
1 |
get "specialization_types/:specialization_type_id/specializations" => "application#specializations", :as => "specializations", :format => :json |
Ed infine implementare il metodo nel controller:
1 2 3 4 5 6 |
def specializations |