Założenia są proste (podam w składni Rails) jest jakaś lista select, na przykład:
<%= select_tag :event_container %>i chciałbym do tej listy dorzucać pracowników z listy
<%= select_tag(:employee_id, options_for_select(Employee.all.map { |employee| [employee.full_name, employee.id] }) %>Chcę sobie kliknąć na listę z pracownikami, a po kliknięciu zaznaczony pracownik ma "przeskoczyć" z jednej listy na drugą. "Przeskoczyć" to znaczy zniknąć z jednej listy, a pojawić się na drugiej i vice versa.
Do widoku wrzucam więc obserwatory:
<%= observe_field "employee_id", :url => {:action => :move_employee_name}, :with => "employee_id" %> <%= observe_field "event_container", :url => {:action => :remove_employee_from_event}, :with => "event_container" %>i tworzę dla nich pliki RJS odpowiednio: move_employee_name.rjs i remove_employee_from_event.rjs. Muszą one być skorelowane z metodami o takich samych nazwach w kontrolerze! Nie zapomnieć!
Wpisy w move_employee_name.rjs dotyczą oczywiście kontrolek select:
page[:event_container].addNewOption @employee.full_name, @employee.id page[:employee_id].removeSelectedOptionWpisy w remove_employee_from_event.rjs są analogiczne
page[:employee_id].addNewOption @employee.full_name, @employee.id page[:event_container].removeSelectedOption
I tu pytanie za 12 punktów: skąd RJS zna te dziwne metody? Mowa oczywiście o ".addNewOption" i ".removeSelectedOption". I od razu odpowiedź: wpisałem je w /public/javascripts/application.js w postaci:
/* Dodawanie metod do szablonów RJS. */ Element.addMethods({ /* Dodawanie nowej opcji do kontrolki select. W tym przypadku jest to "element". */ addNewOption: function(element, option, id) { element.options.add(new Option(option, id)); return element; }, /* Usuwanie zaznaczonej opcji w kontrolce select. Bez parametrów, gdyż funkcja leci po wszystkich. */ removeSelectedOption: function(element) { var i; for (i = element.length - 1; i >= 0; i--) { if (element.options[i].selected) { element.remove(i); return; } } } });Tam jest właśnie cała magia :-)
Sposób opisany tu przeze mnie jest jak najbardziej zgodny z ideą Rails. Daje się łatwo utrzymać w kodzie aplikacji i jest czytelny. Nic tylko brać!