2014-09-01 10 views
5

Ho un'app Rails in cui sto provando a selezionare un elenco di servizi in base alla regione selezionata in un modulo. Finora, ho implementato group_collection_select per fare questo e un po 'di CoffeeScript.CoffeeScript per selezionare i campi modulo in modo dinamico in caso di modifica e carico

Funziona quando si crea un nuovo record e si seleziona una regione. Il comportamento consiste nel mostrare solo le strutture elencate per la regione selezionata. Ciò che non funziona è quando si modifica un record, selezionando le strutture si mostrano tutte le strutture raggruppate per regione invece di vincolare le strutture alla regione selezionata.

Se si seleziona un'altra regione e quindi si seleziona il motivo originale, viene visualizzato l'elenco corretto di strutture.

Mi piacerebbe imparare come rifattorizzare CoffeeScript in cui, quando si modifica il record, la funzione viene attivata sia al caricamento della pagina (durante la modifica) che al cambiamento.

Infine, ci sono casi d'uso quando transfer_from_id è impostato su nil/blank e usiamo un campo di testo chiamato transfer_from_other. Attualmente se non seleziono una funzione e compilo transfer_from_other, a causa del CoffeeScript che carica le strutture in transfer_from_id, verrà impostato il transfer_from_id dalla prima funzione nell'ambito. Mi piacerebbe farlo a dove se nessuna funzione è selezionata, il transfer_from_id è nullo quindi posso usare transfer_from_other.

Ecco ciò che il mio codice è simile:

calls.js.coffee

jQuery -> 
    facilities = $('#call_transfer_from_id').html() 

    $('#call_region_id').change -> 
    region = $('#call_region_id :selected').text() 
    options = $(facilities).filter("optgroup[label=#{region}]").html() 

    if options 
     $('#call_transfer_from_id').html(options) 
    else 
     $('#call_transfer_from_id').empty() 

region.rb

has_many :facilities 

facility.rb

attr_accessible :region_id 
belongs_to :region 

_form.html.erb estratto

 <%= f.label :region %> 
     <%= f.collection_select(:region_id, Region.all, :id, :area, {:include_blank => true}, {:class => 'select', required: true}) %> 
     <%= f.label :Transfer_From %> 
     <%= f.grouped_collection_select :transfer_from_id, Region.order(:area), :active_facilities, :area, :id, :facility_name, {include_blank: true}, class: 'select' %> 
     <%= f.label :Transfer_From_Other%> 
     <%= f.text_field :transfer_from_other %> 

Se la mia domanda e gli esempi non sono chiare, per favore fatemelo sapere e sarò felice di modificare.

+0

provare questo http://stackoverflow.com/questions/11817496/how-to-use-selected-with-grouped-collection-select –

+0

@rkp Grazie ma non è proprio quello che sto cercando. Si prega di rivedere la domanda e se qualcosa non è chiaro fammi sapere. – nulltek

risposta

6

Per quanto riguarda l'aggiornamento della selezione sul caricamento di entrambe le pagine e sulla modifica della selezione, a meno che non manchi qualcosa non è sufficiente scomporre semplicemente la porzione di aggiornamento selezionata nella propria funzione, quindi chiamare una volta al caricamento della pagina, e poi su ogni cambio di selezione?

jQuery -> 
    facilities = $('#call_transfer_from_id').html() 

    update_facilities = -> 
    region = $('#call_region_id :selected').text() 
    options = $(facilities).filter("optgroup[label=#{region}]").html() 

    if options 
     $('#call_transfer_from_id').html(options) 
    else 
     $('#call_transfer_from_id').empty()  

    $('#call_region_id').change -> 
    update_facilities() 

    update_facilities() 

Per quanto riguarda la seconda parte, ogni volta che si aggiorna il #call_transfer_from_id selezionare, si perderà l'opzione vuota. Questa seconda versione aggiunge e seleziona l'opzione vuota ogni volta che si seleziona una regione:

jQuery -> 
    facilities = $('#call_transfer_from_id').html() 

    update_facilities = -> 
    region = $('#call_region_id :selected').text() 
    options = $(facilities).filter("optgroup[label=#{region}]").html() 

    if options 
     # Set the options 
     $('#call_transfer_from_id').html(options) 
     # Add in a blank option at the top 
     $('#call_transfer_from_id').prepend("<option value=''></option>") 
     # Ensure that the blank option is selected 
     $('#call_transfer_from_id option:first').attr("selected", "selected"); 
    else 
     $('#call_transfer_from_id').empty()  

    $('#call_region_id').change -> 
    update_facilities() 

    update_facilities() 
+0

Grazie per il riscaldamento. Funziona sia per il caricamento della pagina che per il cambio di selezione. Ma se lascio vuoto intenzionalmente il campo transfer_from_id e uso transfer_from_other per inserire un indirizzo, il record di chiamata viene creato con transfer_from_id selezionando la prima funzione nell'elenco. Come posso impostarlo su dove transfer_from_id rimane vuoto/zero a meno che non selezioni specificamente una struttura? Stiamo facendo progressi finora e grazie ancora per il vostro aiuto. – nulltek

+0

Ho aggiornato la risposta. Se ti capisco correttamente, stai dicendo che quando scegli una regione e le strutture sono aggiornate, la prima funzione viene automaticamente selezionata in quanto non ci sono opzioni vuote. Supponendo che sto capendo correttamente il problema, allora la risposta modificata dovrebbe fare quello che vuoi. In caso contrario, penso che sarebbe di grande aiuto se potessi creare un violino dimostrando il problema e collegandolo ad esso nella tua domanda. –

+0

Grazie per aver aggiornato la tua risposta. Ho provato questo e ho avuto un problema durante la modifica di una chiamata. Quando si modifica una chiamata, la riga '$ ('# call_transfer_from_id option: first'). Attr (" selected "," selected ");' ha causato il campo facility transfer_from_id per selezionare l'opzione blank. Quando si modifica una chiamata, l'impianto deve rimanere registrato. Così ho rimosso quella riga '$ ('# call_transfer_from_id option: first'). Attr (" selected "," selected ");' e ha lasciato il tuo codice così com'è e sembra funzionare. Verificherò ulteriormente e ti faccio sapere. Grazie per il tuo impegno! – nulltek

0

Così ho giocato in giro con questo problema e credo di aver trovato una soluzione che funziona sia su Chrome e Firefox rispettivamente.

jQuery -> 
    facilities = $('#call_transfer_from_id').html() 

    update_facilities = -> 
    region = $('#call_region_id :selected').text() 
    options = $(facilities).filter("optgroup[label=#{region}]").html() 

    if options 
     # Set the options and include a blank option at the top 
     $('#call_transfer_from_id').html("<option value=''></option>" + options) 
     # Ensure that the blank option is selected 
     $('#call_transfer_from_id').attr("selected", "selected") 
    else 
     $('#call_transfer_from_id').empty() 

    $('#call_region_id').change -> 
    update_facilities() 

    update_facilities() 

sono stato in grado di refactoring e rimuovere una riga di codice e impostare le opzioni e l'opzione vuota in una linea invece di utilizzare anteporre. Per qualche motivo a Firefox non piaceva il metodo ante litter.Quindi, chiamando questa riga: $('#call_transfer_from_id').html("<option value=''></option>" + options) Sono in grado di passare le opzioni e inserire un'opzione vuota all'inizio dell'array.

Finora ho testato su Chrome e Firefox e visualizza il seguente comportamento.

Quando si crea una nuova chiamata, le strutture sono vincolate per regione e nel campo viene visualizzata un'opzione vuota per la selezione. Se si immette un transfer_from_other indirizzo e si lascia transfer_from_id nil, mantiene il valore nullo.

Quando si modifica una chiamata che ha transfer_from_other indirizzo compilato transfer_from_id non popola più con la prima funzione nell'elenco, invece elenca l'opzione vuota (nil).

Durante la modifica di una chiamata che ha assegnato transfer_from_id, mantiene il valore originale del record e continua a vincolare per regione.

Puoi guardare il mio codice e vedere se ha senso. Mi sono imbattuto in questo modo e in qualche modo ho potuto farlo funzionare. Cercando di capire perché questo funziona su entrambi i browser rispetto alla tua risposta, che funziona solo su Chrome.

+0

Ho testato il codice in Safari, quindi sembra sicuro che funzioni in Safari e Chrome, ma che Firefox abbia dei problemi. Se l'unico cambiamento qui è quello di sostituire la riga che ha chiamato "anteporre", allora suggerirei di apportare quella modifica alla mia risposta originale. –

+0

Ho modificato la tua risposta originale per riflettere il cambiamento che ho apportato. Ora la domanda è: perché "anteporre" non funziona in Firefox? Ho pensato che avrebbe funzionato bene. Potrebbe essere forse la versione di jQuery? Sto eseguendo la gemma 'jquery-rails 2.1.4'? – nulltek

Problemi correlati