Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: New args syntax #30

Merged
merged 1 commit into from
Mar 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,14 @@ Actions:
+ **hide**: hides elements (ex. `"data-then": "hide", "data-target": ".errors"`)
+ **slide**: hides elements (using sliding)
+ **fade**: hides elements (using fading)
+ **addClass**: adds classes (ex. `"data-then": "addClass red"`)
+ **addStyle**: adds some styles (ex. `"data-then": "addStyle color: #fb1; font-size: 12px"`)
+ **setText**: set the text of an element (ex. `"data-then": "setText A sample text"`)
+ **setValue**: set the value of an input element (ex. `"data-then": "setValue A sample value"`)
+ **addClass**: adds classes (ex. `"data-then": "addClass", "data-args": "red"`)
+ **addStyle**: adds some styles (ex. `"data-then": "addStyle", "data-args": "color: #fb1; font-size: 12px"`)
+ **setText**: set the text of an element (ex. `"data-then": "setText", "data-args": "A sample text"`)
+ **setValue**: set the value of an input element (ex. `"data-then": "setValue", "data-args": "A sample value"`)
+ **callback**: call a function (with arguments: **data-args**) (ex. `"data-then": "callback a_fun"`)
- **data-args**: arguments passed to the triggered action (or to the callback function)
- **data-else**: action to trigger when the condition check is not true
- **data-args**: arguments passed to the callback function
- **data-else-args**: arguments passed to the triggered else action

Targets:

Expand Down Expand Up @@ -98,14 +99,14 @@ end
- Add 3 classes (*first*, *second*, *third*) if a checkbox is not checked, else add "forth" class:

```rb
data = { if: 'not_checked', then: 'addClass first second third', target: '.grp1', else: 'addClass forth' }
data = { if: 'not_checked', then: 'addClass', args: 'first second third', target: '.grp1', else: 'addClass', 'else-args': 'forth' }
f.input :published, input_html: { data: data }
```

- Set another field value if a string field is blank:

```rb
f.input :title, input_html: { data: { if: 'blank', then: 'setValue 10', target: '#article_position' } }
f.input :title, input_html: { data: { if: 'blank', then: 'setValue', args: '10', target: '#article_position' } }
```

- Use a custom function for conditional check (*title_not_empty()* must be available on global scope) (with alternative syntax for data attributes):
Expand Down
30 changes: 19 additions & 11 deletions app/assets/javascripts/activeadmin/dynamic_fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,27 @@
}

evaluateAction() {
const action = this.el.data('then') || this.el.data('action') || ''
const action_name = action.split(' ', 1)[0]
const else_action = this.el.data('else') || ''
const else_action_name = else_action.split(' ', 1)[0]
const dataAction = this.el.data('then') || this.el.data('action') || ''
const actionName = dataAction.split(' ', 1)[0]
const dataElse = this.el.data('else') || ''
const elseActionName = dataElse.split(' ', 1)[0]

this.action = ACTIONS[action_name]
this.action_arg = action.substring(action.indexOf(' ') + 1)
this.reverse_action = REVERSE_ACTIONS[action_name]
this.else_action = ACTIONS[else_action_name]
this.else_action_arg = else_action.substring(else_action.indexOf(' ') + 1)
this.else_reverse_action = REVERSE_ACTIONS[else_action_name]
this.action = ACTIONS[actionName]
if (actionName == 'callback') {
this.action_arg = dataAction.substring(dataAction.indexOf(' ') + 1)
} else {
this.action_arg = this.el.data('args') || dataAction.substring(dataAction.indexOf(' ') + 1)
}
this.reverse_action = REVERSE_ACTIONS[actionName]
this.else_action = ACTIONS[elseActionName]
if (elseActionName == 'callback') {
this.else_action_arg = dataElse.substring(dataElse.indexOf(' ') + 1)
} else {
this.else_action_arg = this.el.data('else-args') || dataElse.substring(dataElse.indexOf(' ') + 1)
}
this.else_reverse_action = REVERSE_ACTIONS[elseActionName]

return action_name
return actionName
}

evaluateCondition() {
Expand Down
56 changes: 28 additions & 28 deletions spec/dummy/app/admin/posts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,79 +53,79 @@ def add_field(form, name, type, data, override_options = {}, extra_attrs = {})
f.input :data_test, as: :string

# --- if
df111 = { if: 'checked', then: 'addClass red', target: '#post_data_field_111_input label' }
df111 = { if: 'checked', then: 'addClass', args: 'red', target: '#post_data_field_111_input label' }
add_field(f, :data_field_111, :boolean, df111)

df112 = { if: '!checked', then: 'addClass red', target: '#post_data_field_112_input label' }
df112 = { if: '!checked', then: 'addClass', args: 'red', target: '#post_data_field_112_input label' }
add_field(f, :data_field_112, :boolean, df112)

df121 = { if: 'not_checked', then: 'addClass red', target: '#post_data_field_121_input label' }
df121 = { if: 'not_checked', then: 'addClass', args: 'red', target: '#post_data_field_121_input label' }
add_field(f, :data_field_121, :boolean, df121)

df131 = { if: 'blank', then: 'addClass red', target: '#post_data_field_131_input label' }
df131 = { if: 'blank', then: 'addClass', args: 'red', target: '#post_data_field_131_input label' }
add_field(f, :data_field_131, :string, df131)

df132 = { if: 'blank', then: 'addClass red', target: '#post_data_field_132_input label' }
df132 = { if: 'blank', then: 'addClass', args: 'red', target: '#post_data_field_132_input label' }
add_field(f, :data_field_132, :text, df132)

df141 = { if: 'not_blank', then: 'addClass red', target: '#post_data_field_141_input label' }
df141 = { if: 'not_blank', then: 'addClass', args: 'red', target: '#post_data_field_141_input label' }
add_field(f, :data_field_141, :string, df141)

df142 = { if: 'not_blank', then: 'addClass red', target: '#post_data_field_142_input label' }
df142 = { if: 'not_blank', then: 'addClass', args: 'red', target: '#post_data_field_142_input label' }
add_field(f, :data_field_142, :text, df142)

df151 = { if: 'changed', then: 'addClass red', target: '#post_data_field_151_input label' }
df151 = { if: 'changed', then: 'addClass', args: 'red', target: '#post_data_field_151_input label' }
add_field(f, :data_field_151, :boolean, df151)

df152 = { if: 'changed', then: 'addClass red', target: '#post_data_field_152_input label' }
df152 = { if: 'changed', then: 'addClass', args: 'red', target: '#post_data_field_152_input label' }
add_field(f, :data_field_152, :string, df152)

df153 = { if: 'changed', then: 'addClass red', target: '#post_data_field_153_input label' }
df153 = { if: 'changed', then: 'addClass', args: 'red', target: '#post_data_field_153_input label' }
add_field(f, :data_field_153, :text, df153)

# --- eq
df161 = { eq: '161', then: 'addClass red', target: '#post_data_field_161_input label' }
df161 = { eq: '161', then: 'addClass', args: 'red', target: '#post_data_field_161_input label' }
add_field(f, :data_field_161, :string, df161)

df162 = { eq: '162', then: 'addClass red', target: '#post_data_field_162_input label' }
df162 = { eq: '162', then: 'addClass', args: 'red', target: '#post_data_field_162_input label' }
add_field(f, :data_field_162, :select, df162, collection: [161, 162, 163])

df163 = { eq: '163', then: 'addClass red', target: '#post_data_field_163_input label' }
df163 = { eq: '163', then: 'addClass', args: 'red', target: '#post_data_field_163_input label' }
add_field(f, :data_field_163, :text, df163)

df164 = { eq: '!164', then: 'addClass red', target: '#post_data_field_164_input label' }
df164 = { eq: '!164', then: 'addClass', args: 'red', target: '#post_data_field_164_input label' }
add_field(f, :data_field_164, :string, df164)

# --- not
df171 = { not: '171', then: 'addClass red', target: '#post_data_field_171_input label' }
df171 = { not: '171', then: 'addClass', args: 'red', target: '#post_data_field_171_input label' }
add_field(f, :data_field_171, :string, df171)

df172 = { not: '172', then: 'addClass red', target: '#post_data_field_172_input label' }
df172 = { not: '172', then: 'addClass', args: 'red', target: '#post_data_field_172_input label' }
add_field(f, :data_field_172, :select, df172, collection: [171, 172, 173])

df173 = { not: '173', then: 'addClass red', target: '#post_data_field_173_input label' }
df173 = { not: '173', then: 'addClass', args: 'red', target: '#post_data_field_173_input label' }
add_field(f, :data_field_173, :text, df173)

# --- match
df181 = { match: 'Something\s', then: 'addClass red', target: '#post_data_field_181_input label' }
df181 = { match: 'Something\s', then: 'addClass', args: 'red', target: '#post_data_field_181_input label' }
add_field(f, :data_field_181, :string, df181)

# --- mismatch
df191 = { mismatch: '^\d+$', then: 'addClass red', target: '#post_data_field_191_input label' }
df191 = { mismatch: '^\d+$', then: 'addClass', args: 'red', target: '#post_data_field_191_input label' }
add_field(f, :data_field_191, :string, df191)

# --- function
df201 = { function: 'test_fun', then: 'addClass red', target: '#post_data_field_201_input label' }
df201 = { function: 'test_fun', then: 'addClass', args: 'red', target: '#post_data_field_201_input label' }
add_field(f, :data_field_201, :string, df201)

df202 = { function: 'missing_fun', then: 'addClass red', target: '#post_data_field_202_input label' }
df202 = { function: 'missing_fun', then: 'addClass', args: 'red', target: '#post_data_field_202_input label' }
add_field(f, :data_field_202, :string, df202)

df203 = { function: 'test_fun2' }
add_field(f, :data_field_203, :boolean, df203)

# --- addClass
df211 = { if: 'checked', then: 'addClass red', target: '#post_data_field_211_input label' }
df211 = { if: 'checked', then: 'addClass', args: 'red', target: '#post_data_field_211_input label' }
add_field(f, :data_field_211, :boolean, df211)

# --- callback
Expand All @@ -136,7 +136,7 @@ def add_field(form, name, type, data, override_options = {}, extra_attrs = {})
add_field(f, :data_field_222, :boolean, df222)

# --- setValue
df231 = { if: 'checked', then: 'setValue data test', target: '#post_data_test' }
df231 = { if: 'checked', then: 'setValue', args: 'data test', target: '#post_data_test' }
add_field(f, :data_field_231, :boolean, df231)

# --- hide
Expand All @@ -152,23 +152,23 @@ def add_field(form, name, type, data, override_options = {}, extra_attrs = {})
add_field(f, :data_field_261, :boolean, df261)

# --- setText
df271 = { if: 'checked', then: 'setText data test', target: '#post_data_field_271_input .inline-hints' }
df271 = { if: 'checked', then: 'setText', args: 'data test', target: '#post_data_field_271_input .inline-hints' }
add_field(f, :data_field_271, :boolean, df271)

# --- addStyle
df281 = { if: 'checked', then: 'addStyle font-size: 10px; padding: 3px', target: '#post_data_field_281' }
df281 = { if: 'checked', then: 'addStyle', args: 'font-size: 10px; padding: 3px', target: '#post_data_field_281' }
add_field(f, :data_field_281, :boolean, df281, {}, { 'style': 'margin-right: 20px' })

# --- gtarget
df301 = { if: 'checked', then: 'addClass red', gtarget: 'body.active_admin' }
df301 = { if: 'checked', then: 'addClass', args: 'red', gtarget: 'body.active_admin' }
add_field(f, :data_field_301, :boolean, df301)

# This will not work - here only for testing:
df302 = { if: 'checked', then: 'addClass red', target: 'body.active_admin' }
df302 = { if: 'checked', then: 'addClass', args: 'red', target: 'body.active_admin' }
add_field(f, :data_field_302, :boolean, df302)

# --- else
df321 = { if: 'checked', then: 'addClass red', target: '#post_data_field_321_input label', else: 'addClass green' }
df321 = { if: 'checked', then: 'addClass', args: 'red', target: '#post_data_field_321_input label', else: 'addClass', "else-args": "green" }
add_field(f, :data_field_321, :boolean, df321)
end

Expand Down
2 changes: 1 addition & 1 deletion spec/system/dynamic_fields_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def test_change_css(target, options = {})
it 'checks the conditions and actions', retry: 3 do # rubocop:disable RSpec/ExampleLength, RSpec/MultipleExpectations
visit "/admin/posts/#{post.id}/edit"

expect(page).to have_css('#post_data_field_111[data-if="checked"][data-then="addClass red"][data-target="#post_data_field_111_input label"]')
expect(page).to have_css('#post_data_field_111[data-if="checked"][data-then="addClass"][data-args="red"][data-target="#post_data_field_111_input label"]')

# --- if
spec_message('check data-if condition')
Expand Down