tweak 1: Make some column quick-editable on the index list page
Ok… so I want to be quickly able to edit few names, here on the same list page, something like below
Thats simply great!
Now it makes me quickly update any name there itself on the list page, <enter> will make it, <escape> will ignore it, and <tab> will move to the next one. awesome.
And to make it work I just need to have one line of code change
All I need to say is `editable_test_column`, and its done.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ActiveAdmin.register Article do | |
index do | |
selectable_column | |
id_column | |
column :name, :sortable => :name do |resource| | |
editable_text_column resource, :name | |
end | |
column :article_type | |
column :created_at | |
column :updated_at | |
default_actions | |
end | |
end |
And here how it works, you will need to define a couple of things
You need to define editable_text_column, this you could place inside app/admin/lib/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ActiveAdmin | |
module Views | |
class IndexAsTable < ActiveAdmin::Component | |
def editable_text_column resource, attr | |
val = resource.send(attr) | |
val = " " if val.blank? | |
html = %{ | |
<div id='editable_text_column_#{resource.id}' | |
class='editable_text_column' | |
ondblclick='admin.editable_text_column_do(this)' > | |
#{val} | |
</div> | |
<input | |
data-path='#{resource.class.name.tableize}' | |
data-attr='#{attr}' | |
data-resource-id='#{resource.id}' | |
class='editable_text_column admin-editable' | |
id='editable_text_column_#{resource.id}' | |
style='display:none;' /> | |
} | |
html.html_safe | |
end |
Then you will need to add some javascript …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var admin = { | |
init: function(){ | |
admin.set_admin_editable_events(); | |
}, | |
set_admin_editable_events: function(){ | |
$(".admin-editable").live("keypress", function(e){ | |
if ( e.keyCode==27 ) | |
$( e.currentTarget ).hide(); | |
if ( e.keyCode==13 ){ | |
var path = $( e.currentTarget ).attr("data-path"); | |
var attr = $( e.currentTarget ).attr("data-attr"); | |
var resource_id = $( e.currentTarget ).attr("data-resource-id"); | |
var val = $( e.currentTarget ).val(); | |
val = $.trim(val) | |
if (val.length==0) | |
val = " "; | |
$("div#"+$( e.currentTarget ).attr("id")).html(val); | |
$( e.currentTarget ).hide(); | |
var payload = {} | |
resource_class = path.slice(0,–1) // e.g. path = meters, resource_class = meter | |
payload[resource_class] = {}; | |
payload[resource_class][attr] = val; | |
$.put("/admin/"+path+"/"+resource_id, payload).done(function(result){ | |
console.log(result); | |
}); | |
} | |
}); | |
$(".admin-editable").live("blur", function(e){ | |
$( e.currentTarget ).hide(); | |
}); | |
}, | |
editable_text_column_do: function(el){ | |
var input = "input#"+$(el).attr("id") | |
$(input).width( $(el).width()+4 ).height( $(el).height()+4 ); | |
$(input).css({top: ( $(el).offset().top–2 ), left: ( $(el).offset().left–2 ), position:'absolute'}); | |
val = $.trim( $(el).html() ); | |
if (val==" ") | |
val = ""; | |
$(input).val( val ); | |
$(input).show(); | |
$(input).focus(); | |
} | |
} | |
$( document ).ready(function() { | |
admin.init(); | |
}); |
and some css stuff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
input.editable_text_column { | |
background-color: #FBFF8C; | |
border: 1px none #FBFF8C; | |
box-shadow: 0 2px 19px #AAAAAA; | |
color: black; | |
display: none; | |
font-family: serif; | |
font-size: 1em; | |
font-style: italic; | |
height: 30px; | |
position: absolute; | |
text-align: center; | |
vertical-align: middle; | |
width: 180px; | |
z-index: 9090; | |
} | |
div.editable_text_column{ | |
padding:4px; | |
background-color: #f9fbc2; | |
} |
Thats it.
Next, I would love to quickly alter article type say having a dropdown there to save my time
tweak 2: quick editable dropdowns on list page
Ohh, now this is again great!  … no? It actually updates the article type on value change. nice.
Let see the code behind
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ActiveAdmin.register Article do | |
index do | |
selectable_column | |
id_column | |
column :name, :sortable => :name do |resource| | |
editable_text_column resource, :name | |
end | |
column 'Type', :sortable => :article_type do |resource| | |
column_select(resource, :article_type, ["News", "Story", "Case Study", "Business"]) | |
end | |
column :created_at | |
column :updated_at | |
default_actions | |
end | |
end |
and to define `column_select`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ActiveAdmin | |
module Views | |
class IndexAsTable < ActiveAdmin::Component | |
include CustomHelper | |
def column_select resource, attr, list | |
val = resource.send(attr) | |
html = _select list, val, { "attrs" => %{ | |
data-path='#{resource.class.name.tableize}' | |
data-attr='#{attr}' | |
data-resource-id='#{resource.id}' | |
class='admin-selectable' | |
} | |
} | |
html.html_safe | |
end |
CustomHelper is one of my helper modules that really helps me render dropdown the way I need, and provides me some nice options, one may choose to use the default rails select helpers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module CustomHelper | |
def _select set, selected, options={} | |
style = "margin:0;padding:0;#{options["style"]}" | |
selected = options["default"] if selected.blank? | |
cache = options["cache"] || nil | |
id = options["id"] || nil | |
id ||= "ch#{ch_uniq_id}" unless cache.blank? | |
html = "" | |
html << "<select " | |
html << " style='#{style}' " | |
html << " #{options["attrs"]} " | |
html << " data-cache='#{cache}' " unless cache.blank? | |
html << " id='#{id}' " unless id.blank? | |
html << ">" | |
if options["blank"] | |
html << "<option></option>" | |
end | |
unless cache.blank? | |
options_html = Rails.cache.fetch("CustomHelper:#{cache}", expires_in: 1.minute ) { _select_options set, selected, options } | |
else | |
options_html = _select_options set, selected, options | |
end | |
html << options_html | |
html << "</select>" | |
unless cache.blank? | |
html << %{ | |
<script type="text/javascript"> | |
$( document ).ready(function() { | |
$("select##{id}").val("#{selected.to_s.strip}"); | |
}); | |
</script> | |
} | |
end | |
html | |
end | |
def _select_options set, selected, options | |
html = "" | |
selected = selected.to_s.strip | |
arr_match = options["arr_match"] || 0 | |
set.each do |option| | |
check = option | |
value = option | |
if option.is_a? Array | |
check = option[arr_match] | |
value = option[0] | |
option = option[1] | |
end | |
if selected==check.to_s.strip | |
html << "<option value='#{value}' selected>#{option}</option>" | |
else | |
html << "<option value='#{value}'>#{option}</option>" | |
end | |
end | |
html | |
end | |
def ch_uniq_id | |
@ch_uniq_id ||= Time.now.to_i | |
@ch_uniq_id += 1 | |
end | |
end |
Then you need some javascript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var admin = { | |
init: function(){ | |
admin.set_admin_selectable_events(); | |
}, | |
set_admin_selectable_events: function(){ | |
$("select.admin-selectable").live("change", function(e){ | |
var path = $( e.currentTarget ).attr("data-path"); | |
var attr = $( e.currentTarget ).attr("data-attr"); | |
var resource_id = $( e.currentTarget ).attr("data-resource-id"); | |
var val = $( e.currentTarget ).val(); | |
val = $.trim(val) | |
var payload = {} | |
resource_class = path.slice(0,–1) | |
payload[resource_class] = {}; | |
payload[resource_class][attr] = val; | |
$.put("/admin/"+path+"/"+resource_id, payload).done(function(result){ | |
console.log(result); | |
}); | |
}); | |
} | |
} | |
$( document ).ready(function() { | |
admin.init(); | |
}); |
done.
I do have worked out several more tweaks like toggle button for boolean column, show/hide columns on the list page, auto-populate/suggest feature for string filters, one can make use ActiveAdmin icons too, then for one of my requirements I have set up the whole custom header and a dozens of custom pages. I would easily say that ActiveAdmin is just simple and awesome, one can really customize it to the extreme, the code structure will allow you to imagine and implement a number of custom scenarios.
cool! any plan to export this stuff on some gems?
yeah, let me talk to the seanlinsley, this might more suitable as a plugable or addition in some form.
Great stuff – thanks for sharing! I am just getting into the weeds with ActiveAdmin customization.
Thanks, for this. Is there any way filters can be added to each column head with drop downs?
Any example?
Just like there are filters in an excel sheet.
I just added one more custom feature, calling it as readonly mode.
Green means, readonly mode or safe mode, onclick it turns into red, allowing non-GET operations.
This post is great – thanks! Can you please post the code for the toggle button for boolean column? I really need that feature. Thank you!
Hi there!, great tweeks. Really apreciated it. I have receiving this syntax error when im trying to implement
custom_columns.rb:17: syntax error, unexpected end-of-input, expecting keyword_end (SyntaxError)
Could you figure out why?
Thanks in advance
very good explanation , I am new to active admin and this helps a lot.