Repository: vigetlabs/microcosm
Pull request #382 (2017-08-01 16:57:02)

[#381] Add `prepare` hook for action-button
<!--
Please make sure to read the contributing Guidelines:
https://github.com/vigetlabs/microcosm/blob/master/CONTRIBUTING.md
-->

**What kind of change does this PR introduce?**

- Bugfix
- [x] Feature
- Code style update
- Refactor
- Build tools
- Documentation
- Other, please describe:

**Does this PR introduce a breaking change?**

- Yes
- [x] No

If yes, please describe the impact and migration path for existing applications:

**Does this PR fulfill these requirements:**
<!-- (Update "[ ]" to "[x]" to check a box) -->

- [x] All tests are passing
- [x] `yarn pretty` has been run
- [x] Commits reference open issues

**Additional Information**

See #381


codecov-io: # [Codecov](https://codecov.io/gh/vigetlabs/microcosm/pull/382?src=pr&el=h1) Report
> Merging [#382](https://codecov.io/gh/vigetlabs/microcosm/pull/382?src=pr&el=desc) into [master](https://codecov.io/gh/vigetlabs/microcosm/commit/c5d4c408e36b641f22f8d3eed379df1cbe841216?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/vigetlabs/microcosm/pull/382/graphs/tree.svg?token=AaE0FLz9sU&src=pr&height=150&width=650)](https://codecov.io/gh/vigetlabs/microcosm/pull/382?src=pr&el=tree)

```diff
@@          Coverage Diff          @@
##           master   #382   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files          25     25           
  Lines         872    875    +3     
=====================================
+ Hits          872    875    +3
```


| [Impacted Files](https://codecov.io/gh/vigetlabs/microcosm/pull/382?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/addons/action-button.js](https://codecov.io/gh/vigetlabs/microcosm/pull/382?src=pr&el=tree#diff-c3JjL2FkZG9ucy9hY3Rpb24tYnV0dG9uLmpz) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/vigetlabs/microcosm/pull/382?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/vigetlabs/microcosm/pull/382?src=pr&el=footer). Last update [c5d4c40...32458ff](https://codecov.io/gh/vigetlabs/microcosm/pull/382?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

solomonhawk: @nhunzaker Merge when ready!

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2f03dfbe..31270557 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,9 @@
 
 - Domain::setup and constructors receive the key they were mounted at via
   `options.key`.
+- Added `prepare` prop for `ActionButton` that allows developers to specify
+  an extra transformation of the underlying value (e.g. based on the `event`
+  object) before the action gets dispatched.
 
 # 12.11.0
 
diff --git a/docs/api/action-button.md b/docs/api/action-button.md
index 411b9d70..9eaeb0e5 100644
--- a/docs/api/action-button.md
+++ b/docs/api/action-button.md
@@ -76,6 +76,12 @@ should render with.
 
 The parameters that should be passed when broadcasting the provided action.
 
+### prepare(value, event)
+
+Called after the button is clicked but before the action is broadcasted.
+This provides an opportunity to alter the action payload (e.g. based on
+the event object) before it gets dispatched.
+
 ### onClick(event, action)
 
 An event callback executed immediately after the button clicks and the
diff --git a/src/addons/action-button.js b/src/addons/action-button.js
index 681faafa..c4ed8776 100644
--- a/src/addons/action-button.js
+++ b/src/addons/action-button.js
@@ -22,7 +22,8 @@ class ActionButton extends React.PureComponent {
   }
 
   click(event: Event): Action {
-    let action = this.send(this.props.action, this.props.value)
+    let payload = this.props.prepare(this.props.value, event)
+    let action = this.send(this.props.action, payload)
 
     if (action && action instanceof Action) {
       action
@@ -52,6 +53,7 @@ class ActionButton extends React.PureComponent {
     delete props.onCancel
     delete props.onError
     delete props.send
+    delete props.prepare
 
     if (this.props.tag === 'button' && props.type == null) {
       props.type = 'button'
@@ -66,7 +68,8 @@ ActionButton.contextTypes = {
 }
 
 ActionButton.defaultProps = {
-  tag: 'button'
+  tag: 'button',
+  prepare: (value, event) => value
 }
 
 export default ActionButton


Test patch:
diff --git a/test/addons/action-button.test.js b/test/addons/action-button.test.js
index 6926f1d9..f0d35cad 100644
--- a/test/addons/action-button.test.js
+++ b/test/addons/action-button.test.js
@@ -138,6 +138,20 @@ describe('callbacks', function() {
 
     expect(handler).toHaveBeenCalled()
   })
+
+  it('executes prepare with the event and value before pushing the action', function() {
+    let handler = jest.fn()
+
+    let wrapper = mount(<ActionButton prepare={handler} />, {
+      context: {
+        send: () => {}
+      }
+    })
+
+    wrapper.simulate('click')
+
+    expect(handler).toHaveBeenCalled()
+  })
 })
 
 describe('manual operation', function() {