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

ISSUE-35 prevent action callback from dismissing notification #50

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,26 @@ If set to false, the notification will not display the dismiss ('x') button and

### Action

Add a button and a callback function to the notification. If this button is clicked, the callback function is called (if provided) and the notification is dismissed.
Add a button and a callback function to the notification. If this button is clicked, the callback function is called (if provided) and the notification is dismissed (unless `preventDismiss` is true).
Action object has the following properties:

| Name | Type | Default | Description |
|---------------- |--------------- |--------- |----------------------------------------------------------------------------------------------------------------------------------- |
| label | string | null | Title of the action button |
| preventDismiss | bool | false | If set to true, clicking on the button will not cause a notification to be dismissed, just before the callback is invoked. |
| callback | function | null | Function to be invoked when the button is clicked. A callback function takes two arguments: first is the React's `SyntheticMouseEvent` instance and the second is the `callbackArgument` object. Please note that `this` in a callback function is assigned to the `notification` itself, so you can reference it later in the callback. However, this is valid only in case a callback function is defined like in the example below. Otherwise `this` could have a different value. |
| callbackArgument | object | null | A custom object which will be passed into the callback as the second argument. Passing the callback argument is especially useful when your callback function is not defined inline, but in other place then your notification object. |

```js
notification = {
[...],
action: {
label: 'Button name',
callback: function() {
console.log('Notification button clicked!');
preventDismiss: true,
callback: function(event, param) {
console.log('Callback invoked by the event', event, "with param", param.name);
}
callbackArgument: {name: 'foo'}
}
}

Expand Down
15 changes: 15 additions & 0 deletions example/src/scripts/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ NotificationSystemExample = React.createClass({
level: 'error',
position: 'tl'
},
{
title: 'Ups!',
message: 'Something bad happened :(',
level: 'error',
position: 'tl',
action: {
label: 'Details',
preventDismiss: true,
callback: function (event, param) {
console.log('Details clicked', event, 'in notification', this);
alert(param.code + ': ' + param.message);
},
callbackArgument: {code: 500, message: 'Internal server error'}
}
},
{
title: 'Advise!',
message: 'Showing all possible notifications works better on a larger screen',
Expand Down
9 changes: 7 additions & 2 deletions src/NotificationItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,14 @@ var NotificationItem = React.createClass({
var notification = this.props.notification;

event.preventDefault();
this._hideNotification();
if (notification.action.preventDismiss) {
event.stopPropagation(); // do not let _dismiss method (fired on parent onClick event) to be invoked
} else {
this._hideNotification();
}

if (typeof notification.action.callback === 'function') {
notification.action.callback();
notification.action.callback.call(notification, event, notification.action.callbackArgument);
}
},

Expand Down
39 changes: 38 additions & 1 deletion test/notification-system.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ describe('Notification Component', function() {
done();
});

it('should not dismiss the notificaion on click if dismissible is false', done => {
it('should not dismiss the notification on click if dismissible is false', done => {
notificationObj.dismissible = false;
component.addNotification(notificationObj);
let notification = TestUtils.findRenderedDOMComponentWithClass(instance, 'notification');
Expand All @@ -200,6 +200,20 @@ describe('Notification Component', function() {
done();
});

it('should not dismiss the notification on click if preventDismiss is true', done => {
notificationObj.action = {
label: 'Click me',
preventDismiss: true,
callback: function() {}
};
component.addNotification(notificationObj);
let button = TestUtils.findRenderedDOMComponentWithClass(instance, 'notification-action-button');
TestUtils.Simulate.click(button);
let notificationAfterClicked = TestUtils.findRenderedDOMComponentWithClass(instance, 'notification-action-button');
expect(notificationAfterClicked).toExist();
done();
});

it('should render a button if action property is passed', done => {
defaultNotification.action = {
label: 'Click me',
Expand Down Expand Up @@ -228,6 +242,29 @@ describe('Notification Component', function() {
done();
});

it('should execute a callback function with proper arguments when notification button is clicked', done => {
let thisNotification = undefined,
event = undefined,
callArg = undefined;
notificationObj.action = {
label: 'Click me',
callback: function(e, param) {
thisNotification = this;
callArg = param.value;
event = e;
},
callbackArgument: {value: 'foo'}
};

component.addNotification(notificationObj);
let button = TestUtils.findRenderedDOMComponentWithClass(instance, 'notification-action-button');
TestUtils.Simulate.click(button);
expect('Click me').toEqual(thisNotification.action.label);
expect(callArg).toEqual('foo');
expect(event).toBeAn('object');
done();
});

it('should accept an action without callback function defined', done => {
notificationObj.action = {
label: 'Click me'
Expand Down