diff --git a/packages/casl-react/README.md b/packages/casl-react/README.md
index 977935e50..0646a978c 100644
--- a/packages/casl-react/README.md
+++ b/packages/casl-react/README.md
@@ -186,7 +186,7 @@ For example, the code below reads as `Can I create a Post`.
There are several other property aliases which allow to construct a readable question:
-* use `a` alias when you check by Type
+* use `a` (or `an`) alias when you check by Type
```jsx
...
@@ -227,6 +227,14 @@ There are several other property aliases which allow to construct a readable que
...
```
+* use `passThrough` if you want to customize behavior of `` component, for example disable button instead of hiding it:
+
+```jsx
+
+ {can => }
+
+```
+
## Want to help?
diff --git a/packages/casl-react/spec/Can.spec.js b/packages/casl-react/spec/Can.spec.js
index d65927246..63ac340bc 100644
--- a/packages/casl-react/spec/Can.spec.js
+++ b/packages/casl-react/spec/Can.spec.js
@@ -25,10 +25,10 @@ describe('`Can` component', () => {
expect(() => validateProps(Can, props)).not.to.throw(Error)
})
- it('passes ability instance as an argument to "children" function', () => {
+ it('passes ability check value and instance as arguments to "children" function', () => {
const component = renderer.create(e(Can, { I: 'read', a: 'Post', ability }, children))
- expect(children).to.have.been.called.with.exactly(ability)
+ expect(children).to.have.been.called.with.exactly(ability.can('read', 'Post'), ability)
})
it('requires to pass "a" or "this" or "of" as string or object', () => {
@@ -154,6 +154,15 @@ describe('`Can` component', () => {
expect(component.toJSON()).to.deep.equal(renderedChildren)
})
+
+ it('always renders children if `passThrough` prop is `true`', () => {
+ const component = renderer.create(
+ e(Can, { I: 'delete', a: 'Post', passThrough: true, ability }, child)
+ )
+
+ expect(ability.can('delete', 'Post')).to.be.false
+ expect(component.toJSON().children).to.deep.equal([child.props.children])
+ })
})
function validateProps(Component, props, propName) {
diff --git a/packages/casl-react/spec/factory.spec.js b/packages/casl-react/spec/factory.spec.js
index fb3ed88fc..6814d6f72 100644
--- a/packages/casl-react/spec/factory.spec.js
+++ b/packages/casl-react/spec/factory.spec.js
@@ -54,7 +54,7 @@ describe('Factory methods which create `Can` component', () => {
const element = e(ContextualCan, { I: 'read', a: 'Post', ability }, child)
const component = renderer.create(element)
- expect(child).to.have.been.called.with.exactly(ability)
+ expect(child).to.have.been.called.with(ability)
})
it('expects `Ability` instance to be provided by context Provider', () => {
@@ -63,7 +63,7 @@ describe('Factory methods which create `Can` component', () => {
)
const component = renderer.create(App)
- expect(child).to.have.been.called.with.exactly(ability)
+ expect(child).to.have.been.called.with(ability)
})
})
})
diff --git a/packages/casl-react/src/Can.js b/packages/casl-react/src/Can.js
index d4890cc32..c98731abd 100644
--- a/packages/casl-react/src/Can.js
+++ b/packages/casl-react/src/Can.js
@@ -28,6 +28,7 @@ export default class Can extends PureComponent {
do: alias('I', PropTypes.string.isRequired),
on: alias('this a of an', REQUIRED_OBJECT_OR_STRING),
not: PropTypes.bool,
+ passThrough: PropTypes.bool,
children: PropTypes.any.isRequired,
ability: PropTypes.instanceOf(Ability).isRequired
};
@@ -86,13 +87,14 @@ export default class Can extends PureComponent {
}
render() {
- return this.state.allowed ? this.renderChildren() : null;
+ const canRender = this.props.passThrough || this.state.allowed;
+ return canRender ? this.renderChildren() : null;
}
renderChildren() {
const { children } = this.props;
const elements = typeof children === 'function'
- ? children(this.state.ability)
+ ? children(this.state.allowed, this.state.ability)
: children;
return renderChildren(elements);
diff --git a/packages/casl-react/src/factory.js b/packages/casl-react/src/factory.js
index 8c2fda317..747a8fcb9 100644
--- a/packages/casl-react/src/factory.js
+++ b/packages/casl-react/src/factory.js
@@ -23,7 +23,8 @@ export function createContextualCan(Consumer) {
I: props.I || props.do,
a: props.on || props.a || props.an || props.of || props.this,
not: props.not,
- children: props.children
+ children: props.children,
+ passThrough: props.passThrough,
}));
};
}