Skip to content

Commit

Permalink
Added filtering for polymorphic association objects
Browse files Browse the repository at this point in the history
Until now, for polymorphic associations, a simple select tag was used, without
filtering option. This commit adds filtering that easily works with switching
association class.

For each association class we need a path to load records from. For simple
association, this is hardcoded in the `select` tag, for polymorphic one, we need
to save them (a div with specific `data` attribute is generated) and switch
whenever object type is switched.

Switching type is a 3 step process:
* update `data-options` attribute of select tag
* destroy filtering object
* create filtering object with new options

Additionally, to avoid weird CSS behaviour, a fix to CSS generation was
introduced. Without it, the object type field was moved to the right (since
object value field had `float: left;` attribute set

Use filter select for polymorphic association fields
  • Loading branch information
arnvald authored and shekibobo committed May 3, 2018
1 parent 629b7b2 commit 8ad0793
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 28 deletions.
16 changes: 9 additions & 7 deletions app/assets/javascripts/rails_admin/ra.filtering-select.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,22 @@
button: null,
input: null,
select: null,
filtering_select: null,

_create: function() {
var filtering_select = this.element.siblings(
this.filtering_select = this.element.siblings(
'[data-input-for="' + this.element.attr('id') + '"]'
);

// When using the browser back and forward buttons, it is possible that
// the autocomplete field will be cached which causes duplicate fields
// to be generated.
if (filtering_select.length > 0) {
this.input = filtering_select.children('input');
this.button = filtering_select.children('.input-group-btn');
if (this.filtering_select.length > 0) {
this.input = this.filtering_select.children('input');
this.button = this.filtering_select.children('.input-group-btn');
} else {
this.element.hide();
filtering_select = this._inputGroup(this.element.attr('id'));
this.filtering_select = this._inputGroup(this.element.attr('id'));
this.input = this._inputField();
this.button = this._buttonField();
}
Expand All @@ -56,7 +57,7 @@
this._overloadRenderItem();
this._autocompleteDropdownEvent(this.button);

return filtering_select.append(this.input)
return this.filtering_select.append(this.input)
.append(this.button)
.insertAfter(this.element);
},
Expand Down Expand Up @@ -201,7 +202,7 @@
return $('<div>')
.addClass('input-group filtering-select col-sm-2')
.attr('data-input-for', inputFor)
.css('float', 'left');
.css('float', this.element.css("float"));
},

_initAutocomplete: function() {
Expand Down Expand Up @@ -286,6 +287,7 @@
this.input.remove();
this.button.remove();
this.element.show();
this.filtering_select.remove();
$.Widget.prototype.destroy.call(this);
}
});
Expand Down
24 changes: 6 additions & 18 deletions app/assets/javascripts/rails_admin/ra.widgets.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -151,25 +151,13 @@ $(document).on 'rails_admin.dom_ready', (e, content) ->
field = type_select.parents('.control-group').first()
object_select = field.find('select').last()
urls = type_select.data('urls')

type_select.on 'change', (e) ->
if $(this).val() is ''
object_select.html('<option value=""></option>')
else
$.ajax
url: urls[type_select.val()]
data:
compact: true
all: true
beforeSend: (xhr) ->
xhr.setRequestHeader("Accept", "application/json")
success: (data, status, xhr) ->
html = $('<option></option>')
$(data).each (i, el) ->
option = $('<option></option>')
option.attr('value', el.id)
option.text(el.label)
html = html.add(option)
object_select.html(html)
selected_type = type_select.val().toLowerCase()
selected_data = $("##{selected_type}-js-options").data('options')
object_select.data('options', selected_data)
object_select.filteringSelect("destroy")
object_select.filteringSelect selected_data


# simplemde
Expand Down
21 changes: 18 additions & 3 deletions app/views/rails_admin/main/_form_polymorphic_association.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,25 @@
type_collection = field.polymorphic_type_collection
type_column = field.association.foreign_type.to_s
selected_type = field.bindings[:object].send(type_column)
collection = field.associated_collection(selected_type)
selected = field.bindings[:object].send(field.association.name)
collection = selected ? [[field.formatted_value, selected.id]] : [[]]
column_type_dom_id = form.dom_id(field).sub(field.method_name.to_s, type_column)
current_action = params[:action].in?(['create', 'new']) ? 'create' : 'update'

default_options = { float_left: false }

js_data = type_collection.inject({}) do |options, model|
model_name = model[0].downcase.parameterize.underscore
source_abstract_model = RailsAdmin.config(form.object.class).abstract_model
options.merge(model_name.gsub("_", "") => {
xhr: true,
remote_source: index_path(model_name, source_object_id: form.object.id, source_abstract_model: source_abstract_model.to_param, current_action: current_action, compact: true),
float_left: false
})
end

.form-inline
= form.select type_column, type_collection, {include_blank: true, selected: selected_type}, class: "form-control", id: column_type_dom_id, data: { polymorphic: true, urls: field.polymorphic_type_urls.to_json }
= form.select field.method_name, collection, {include_blank: true, selected: selected.try(:id)}, class: "form-control"
- js_data.each do |model, value|
%div{id: "#{model}-js-options", data: { options: value.to_json } }
= form.select type_column, type_collection, {include_blank: true, selected: selected_type}, class: "form-control", id: column_type_dom_id, data: { polymorphic: true, urls: field.polymorphic_type_urls.to_json }, style: "float: left; margin-right: 10px;"
= form.select field.method_name, collection, {include_blank: true, selected: selected.try(:id)}, class: "form-control", data: { filteringselect: true, options: js_data[selected_type.try(:downcase)] || default_options }, placeholder: 'Search'

0 comments on commit 8ad0793

Please sign in to comment.