Skip to content

Commit

Permalink
[added] buttonComponentClass prop for Pagination
Browse files Browse the repository at this point in the history
wrap pagination buttons in a custom element

usage: <Pagination ... buttonComponentClass={ButtonWrapper}/>
where ButtonWrapper is your custom element

default behavior (no prop given) remains unchanged

note: Bootstrap css targets .pagination > li > a
  • Loading branch information
Igor Scekic committed Jul 24, 2015
1 parent ac7ada5 commit 6a541ff
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 12 deletions.
30 changes: 22 additions & 8 deletions src/Pagination.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React from 'react';
import classNames from 'classnames';
import BootstrapMixin from './BootstrapMixin';
import PaginationButton from './PaginationButton';
import CustomPropTypes from './utils/CustomPropTypes';
import SafeAnchor from './SafeAnchor';

const Pagination = React.createClass({
mixins: [BootstrapMixin],
Expand All @@ -15,7 +17,11 @@ const Pagination = React.createClass({
last: React.PropTypes.bool,
prev: React.PropTypes.bool,
next: React.PropTypes.bool,
onSelect: React.PropTypes.func
onSelect: React.PropTypes.func,
/**
* You can use a custom element for the buttons
*/
buttonComponentClass: CustomPropTypes.elementType
},

getDefaultProps() {
Expand All @@ -28,6 +34,7 @@ const Pagination = React.createClass({
prev: false,
next: false,
ellipsis: true,
buttonComponentClass: SafeAnchor,
bsClass: 'pagination'
};
},
Expand All @@ -40,7 +47,8 @@ const Pagination = React.createClass({
activePage,
items,
onSelect,
ellipsis
ellipsis,
buttonComponentClass
} = this.props;

if(maxButtons){
Expand Down Expand Up @@ -68,7 +76,8 @@ const Pagination = React.createClass({
key={pagenumber}
eventKey={pagenumber}
active={pagenumber === activePage}
onSelect={onSelect}>
onSelect={onSelect}
buttonComponentClass={buttonComponentClass}>
{pagenumber}
</PaginationButton>
);
Expand All @@ -78,7 +87,8 @@ const Pagination = React.createClass({
pageButtons.push(
<PaginationButton
key='ellipsis'
disabled>
disabled
buttonComponentClass={buttonComponentClass}>
<span aria-label='More'>...</span>
</PaginationButton>
);
Expand All @@ -97,7 +107,8 @@ const Pagination = React.createClass({
key='prev'
eventKey={this.props.activePage - 1}
disabled={this.props.activePage === 1}
onSelect={this.props.onSelect}>
onSelect={this.props.onSelect}
buttonComponentClass={this.props.buttonComponentClass}>
<span aria-label='Previous'>&lsaquo;</span>
</PaginationButton>
);
Expand All @@ -113,7 +124,8 @@ const Pagination = React.createClass({
key='next'
eventKey={this.props.activePage + 1}
disabled={this.props.activePage >= this.props.items}
onSelect={this.props.onSelect}>
onSelect={this.props.onSelect}
buttonComponentClass={this.props.buttonComponentClass}>
<span aria-label='Next'>&rsaquo;</span>
</PaginationButton>
);
Expand All @@ -129,7 +141,8 @@ const Pagination = React.createClass({
key='first'
eventKey={1}
disabled={this.props.activePage === 1 }
onSelect={this.props.onSelect}>
onSelect={this.props.onSelect}
buttonComponentClass={this.props.buttonComponentClass}>
<span aria-label='First'>&laquo;</span>
</PaginationButton>
);
Expand All @@ -145,7 +158,8 @@ const Pagination = React.createClass({
key='last'
eventKey={this.props.items}
disabled={this.props.activePage >= this.props.items}
onSelect={this.props.onSelect}>
onSelect={this.props.onSelect}
buttonComponentClass={this.props.buttonComponentClass}>
<span aria-label='Last'>&raquo;</span>
</PaginationButton>
);
Expand Down
12 changes: 9 additions & 3 deletions src/PaginationButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import classNames from 'classnames';
import BootstrapMixin from './BootstrapMixin';
import createSelectedEvent from './utils/createSelectedEvent';
import SafeAnchor from './SafeAnchor';
import CustomPropTypes from './utils/CustomPropTypes';

const PaginationButton = React.createClass({
mixins: [BootstrapMixin],
Expand All @@ -15,7 +15,11 @@ const PaginationButton = React.createClass({
]),
onSelect: React.PropTypes.func,
disabled: React.PropTypes.bool,
active: React.PropTypes.bool
active: React.PropTypes.bool,
/**
* You can use a custom element for this component
*/
buttonComponentClass: CustomPropTypes.elementType
},

getDefaultProps() {
Expand Down Expand Up @@ -44,9 +48,11 @@ const PaginationButton = React.createClass({
...anchorProps
} = this.props;

let ButtonComponentClass = this.props.buttonComponentClass;

return (
<li className={classNames(className, classes)}>
<SafeAnchor
<ButtonComponentClass
{...anchorProps}
onClick={this.handleClick} />
</li>
Expand Down
2 changes: 1 addition & 1 deletion test/OverlayTriggerSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('OverlayTrigger', function() {
const overlayTrigger = React.findDOMNode(instance);
ReactTestUtils.Simulate.click(overlayTrigger);

expect(document.getElementsByClassName('test-overlay').length).to.equal(1)
expect(document.getElementsByClassName('test-overlay').length).to.equal(1);
});

it('Should pass transition callbacks to Transition', function (done) {
Expand Down
61 changes: 61 additions & 0 deletions test/PaginationSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,65 @@ describe('Pagination', function () {
assert.include(React.findDOMNode(pageButtons[0]).className, 'disabled');
assert.include(React.findDOMNode(pageButtons[1]).className, 'disabled');
});

it('Should wrap buttons in SafeAnchor when no buttonComponentClass prop is supplied', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Pagination
maxButtons={2}
activePage={1}
items={2} />
);
let pageButtons = ReactTestUtils.scryRenderedDOMComponentsWithTag(instance, 'li');

let tagName = 'A';

assert.equal(React.findDOMNode(pageButtons[0]).children[0].tagName, tagName);
assert.equal(React.findDOMNode(pageButtons[1]).children[0].tagName, tagName);

assert.equal(React.findDOMNode(pageButtons[0]).children[0].getAttribute('href'), '');
assert.equal(React.findDOMNode(pageButtons[1]).children[0].getAttribute('href'), '');
});

it('Should wrap each button in a buttonComponentClass when it is present', function () {
class DummyElement extends React.Component {
render() {
return <div {...this.props}/>;
}
}

let instance = ReactTestUtils.renderIntoDocument(
<Pagination
maxButtons={2}
activePage={1}
items={2}
buttonComponentClass={DummyElement} />
);
let pageButtons = ReactTestUtils.scryRenderedDOMComponentsWithTag(instance, 'li');

let tagName = 'DIV';

assert.equal(React.findDOMNode(pageButtons[0]).children[0].tagName, tagName);
assert.equal(React.findDOMNode(pageButtons[1]).children[0].tagName, tagName);
});

it('Should call onSelect with custom buttonComponentClass', function (done) {
class DummyElement extends React.Component {
render() {
return <div {...this.props}/>;
}
}

function onSelect(event, selectedEvent) {
assert.equal(selectedEvent.eventKey, 3);
done();
}

let instance = ReactTestUtils.renderIntoDocument(
<Pagination items={5} onSelect={onSelect} buttonComponentClass={DummyElement}/>
);

ReactTestUtils.Simulate.click(
ReactTestUtils.scryRenderedDOMComponentsWithTag(instance, 'div')[2]
);
});
});

0 comments on commit 6a541ff

Please sign in to comment.