{"id":13747262,"url":"https://github.com/blocknotes/activeadmin_dynamic_fields","last_synced_at":"2025-04-12T13:28:31.803Z","repository":{"id":24988346,"uuid":"102932215","full_name":"blocknotes/activeadmin_dynamic_fields","owner":"blocknotes","description":"ActiveAdmin plugin to add dynamic behaviors to fields","archived":false,"fork":false,"pushed_at":"2025-04-05T09:26:11.000Z","size":176,"stargazers_count":116,"open_issues_count":1,"forks_count":19,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-05T10:25:32.539Z","etag":null,"topics":["activeadmin","activeadmin-plugin","rails","rails5","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blocknotes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["blocknotes"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2017-09-09T06:23:59.000Z","updated_at":"2025-04-05T09:26:14.000Z","dependencies_parsed_at":"2024-06-20T21:49:52.025Z","dependency_job_id":"99b264be-c037-4589-b5ab-0d1ca12a25f6","html_url":"https://github.com/blocknotes/activeadmin_dynamic_fields","commit_stats":{"total_commits":76,"total_committers":7,"mean_commits":"10.857142857142858","dds":0.5394736842105263,"last_synced_commit":"71dfeade710d25fc253674cc1caff9439014e216"},"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blocknotes%2Factiveadmin_dynamic_fields","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blocknotes%2Factiveadmin_dynamic_fields/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blocknotes%2Factiveadmin_dynamic_fields/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blocknotes%2Factiveadmin_dynamic_fields/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blocknotes","download_url":"https://codeload.github.com/blocknotes/activeadmin_dynamic_fields/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248573104,"owners_count":21126764,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["activeadmin","activeadmin-plugin","rails","rails5","ruby"],"created_at":"2024-08-03T06:01:23.130Z","updated_at":"2025-04-12T13:28:31.780Z","avatar_url":"https://github.com/blocknotes.png","language":"Ruby","readme":"# ActiveAdmin Dynamic Fields\n[![gem version](https://badge.fury.io/rb/activeadmin_dynamic_fields.svg)](https://badge.fury.io/rb/activeadmin_dynamic_fields) [![gem downloads](https://badgen.net/rubygems/dt/activeadmin_dynamic_fields)](https://rubygems.org/gems/activeadmin_dynamic_fields) [![linters](https://github.com/blocknotes/activeadmin_dynamic_fields/actions/workflows/linters.yml/badge.svg)](https://github.com/blocknotes/activeadmin_dynamic_fields/actions/workflows/linters.yml) [![specs](https://github.com/blocknotes/activeadmin_dynamic_fields/actions/workflows/specs_rails70.yml/badge.svg)](https://github.com/blocknotes/activeadmin_dynamic_fields/actions/workflows/specs_rails70.yml)\n\nAn Active Admin plugin to add dynamic behaviors to some fields.\n\nFeatures:\n\n- set conditional checks on fields\n- trigger actions on target elements\n- inline field editing\n- create links to load some content in a dialog\n\nThe easiest way to show how this plugin works is looking the examples [below](#examples).\n\nPlease :star: if you like it.\n\n## Install\n\nFirst, add the gem to your ActiveAdmin project: `gem 'activeadmin_dynamic_fields'` (and execute `bundle`)\n\nIf you installed Active Admin **without Webpacker** support:\n- add at the end of your ActiveAdmin javascripts (_app/assets/javascripts/active_admin.js_):\n\n```js\n//= require activeadmin/dynamic_fields\n```\n\nOtherwise **with Webpacker**:\n\n- Execute in your project root:\n\n```sh\nyarn add blocknotes/activeadmin_dynamic_fields\n```\n\n- Add to your *app/javascript/packs/active_admin.js*:\n\n```js\nrequire('activeadmin_dynamic_fields')\n```\n\n## Options\n\nOptions are passed to fields using *input_html* parameter as *data* attributes.\n\nConditions:\n\n- **data-if**: check a condition, values:\n  + **checked**: check if a checkbox is checked (ex. `\"data-if\": \"checked\"`)\n  + **not_checked**: check if a checkbox is not checked (equivalent to `\"data-if\": \"!checked\"`)\n  + **blank**: check if a field is blank\n  + **not_blank**: check if a field is not blank\n  + **changed**: check if the value of an input is changed (dirty)\n- **data-eq**: check if a field has a specific value (ex. `\"data-eq\": \"42\"` or `\"data-eq\": \"!5\"`)\n- **data-not**: check if a field has not a specific value (equivalent to `\"data-eq\": \"!something\"`)\n- **data-match**: check if a field match a regexp\n- **data-mismatch**: check if a field doesn't match a regexp (ex. `\"data-mismatch\": \"^\\d+$\"`)\n- **data-function**: check the return value of a custom function (ex. `\"data-function\": \"my_check\"`)\n\nActions:\n\n- **data-then**: action to trigger (alias **data-action**), values:\n  + **hide**: hides elements (ex. `\"data-then\": \"hide\", \"data-target\": \".errors\"`)\n  + **slide**: hides elements (using sliding)\n  + **fade**: hides elements (using fading)\n  + **addClass**: adds classes (ex. `\"data-then\": \"addClass\", \"data-args\": \"red\"`)\n  + **addStyle**: adds some styles (ex. `\"data-then\": \"addStyle\", \"data-args\": \"color: #fb1; font-size: 12px\"`)\n  + **setText**: set the text of an element (ex. `\"data-then\": \"setText\", \"data-args\": \"A sample text\"`)\n  + **setValue**: set the value of an input element (ex. `\"data-then\": \"setValue\", \"data-args\": \"A sample value\"`)\n  + **callback**: call a function (with arguments: **data-args**) (ex. `\"data-then\": \"callback a_fun\"`)\n- **data-args**: arguments passed to the triggered action (or to the callback function)\n- **data-else**: action to trigger when the condition check is not true\n- **data-else-args**: arguments passed to the triggered else action\n\nTargets:\n\n- **data-target**: target css selector (from parent fieldset, look for the closest match)\n- **data-gtarget**: target css selector globally\n\nA check condition or a custom check function are required. A trigger action is required too, unless you are using a custom function (in that case it is optional).\n\n## Examples\n\n### Dynamic fields examples\n\n- A checkbox that hides other fields if is checked (ex. model *Article*):\n\n```rb\nform do |f|\n  f.inputs 'Article' do\n    f.input :published, input_html: { data: { if: 'checked', then: 'hide', target: '.grp1' } }\n    f.input :online_date, wrapper_html: { class: 'grp1' }\n    f.input :draft_notes, wrapper_html: { class: 'grp1' }\n  end\n  f.actions\nend\n```\n\n- Add 3 classes (*first*, *second*, *third*) if a checkbox is not checked, else add \"forth\" class:\n\n```rb\ndata = { if: 'not_checked', then: 'addClass', args: 'first second third', target: '.grp1', else: 'addClass', 'else-args': 'forth' }\nf.input :published, input_html: { data: data }\n```\n\n- Set another field value if a string field is blank:\n\n```rb\nf.input :title, input_html: { data: { if: 'blank', then: 'setValue', args: '10', target: '#article_position' } }\n```\n\n- Use a custom function for conditional check (*title_not_empty()* must be available on global scope) (with alternative syntax for data attributes):\n\n```rb\nattrs = { 'data-function': 'title_empty', 'data-then': 'slide', 'data-target': '#article_description_input' }\nf.input :title, input_html: attrs\n```\n\n```js\nfunction title_empty(el) {\n  return ($('#article_title').val().trim() === '');\n}\n```\n\n- Call a callback function as action:\n\n```rb\ndata = { if: 'checked', then: 'callback set_title', args: '[\"Unpublished !\"]' }\nf.input :published, input_html: { data: data }\n```\n\n```js\nfunction set_title(args) {\n  if($('#article_title').val().trim() === '') {\n    $('#article_title').val(args[0]);\n    $('#article_title').trigger('change');\n  }\n}\n```\n\n- Custom function without action:\n\n```rb\ncollection = [['Cat 1', 'cat1'], ['Cat 2', 'cat2'], ['Cat 3', 'cat3']]\nf2.input :category, as: :select, collection: collection, input_html: { 'data-function': 'on_change_category' }\n```\n\n```js\nfunction on_change_category(el) {\n  var target = el.closest('fieldset').find('.pub');\n  target.prop('checked', (el.val() == 'cat2');\n  target.trigger('change');\n}\n```\n\n### Inline editing examples\n\n- Prepare a custom member action to save data, an *update* helper function is available (third parameter is optional, allow to filter using strong parameters):\n\n```rb\nmember_action :save, method: [:post] do\n  render ActiveAdmin::DynamicFields.update(resource, params)\n  # render ActiveAdmin::DynamicFields.update(resource, params, [:published])\n  # render ActiveAdmin::DynamicFields.update(resource, params, Article::permit_params)\nend\n```\n\n- In *index* config:\n\n```rb\n# Edit a string:\ncolumn :title do |row|\n  div row.title, ActiveAdmin::DynamicFields.edit_string(:title, save_admin_article_path(row.id))\nend\n# Edit a boolean:\ncolumn :published do |row|\n  status_tag row.published, ActiveAdmin::DynamicFields.edit_boolean(:published, save_admin_article_path(row.id), row.published)\nend\n# Edit a select ([''] allow to have a blank value):\ncolumn :author do |row|\n  select ActiveAdmin::DynamicFields.edit_select(:author_id, save_admin_article_path(row.id)) do\n    options_for_select([''] + Author.pluck(:name, :id), row.author_id)\n  end\nend\n```\n\n- In *show* config (inside `attributes_table` block):\n```rb\nrow :title do |row|\n  div row.title, ActiveAdmin::DynamicFields.edit_string(:title, save_admin_article_path(row.id))\nend\n```\n\n### Dialog example\n\nExample with 2 models: *Author* and *Article*\n\nPrepare the content dialog - in Active Admin Author config:\n\n```rb\nActiveAdmin.register Author do\n  # ...\n  member_action :dialog do\n    record = resource\n    context = Arbre::Context.new do\n      dl do\n        %i[name age created_at].each do |field|\n          dt \"#{Author.human_attribute_name(field)}:\"\n          dd record[field]\n        end\n      end\n    end\n    render plain: context\n  end\n  # ...\nend\n```\n\nAdd a link to show the dialog - in Active Admin Article config:\n\n```rb\nActiveAdmin.register Article do\n  # ...\n  show do |object|\n    attributes_table do\n      # ...\n      row :author do\n        link_to object.author.name, dialog_admin_author_path(object.author), title: object.author.name, 'data-df-dialog': true, 'data-df-icon': true\n      end\n    end\n  end\n  # ...\nend\n```\n\nThe link url is loaded via AJAX before opening the dialog.\n\n## Development\n\nProject created by [Mattia Roccoberton](http://blocknot.es), thanks also to the good guys that opened issues and pull requests from time to time.\n\nFor development information please check [this document](extra/development.md).\n\n## Do you like it? Star it!\n\nIf you use this component just star it. A developer is more motivated to improve a project when there is some interest. My other [Active Admin components](https://github.com/blocknotes?utf8=✓\u0026tab=repositories\u0026q=activeadmin\u0026type=source).\n\nOr consider offering me a coffee, it's a small thing but it is greatly appreciated: [about me](https://www.blocknot.es/about-me).\n\n## License\n\nThe gem is available as open-source under the terms of the [MIT](LICENSE.txt).\n","funding_links":["https://github.com/sponsors/blocknotes"],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblocknotes%2Factiveadmin_dynamic_fields","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblocknotes%2Factiveadmin_dynamic_fields","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblocknotes%2Factiveadmin_dynamic_fields/lists"}