Skip to content

Commit 2e0d514

Browse files
authored
feat: Allow arbitrary data attributes to be set (#65) ✨
* feat: Allow arbitrary data attributes to be set * chore: Fix Bad merge * test: Add tests to ensure data attributes are being rendered * chore: Fix codeclimate issue * docs: Adding dataset property 📚
1 parent b7fe7bc commit 2e0d514

File tree

6 files changed

+49
-4
lines changed

6 files changed

+49
-4
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ Data for rendering the tree select items. The object requires the following stru
200200
className, // optional: Additional css class for the node. This is helpful to style the nodes your way
201201
tagClassName, // optional: Css class for the corresponding tag. Use this to add custom style the pill corresponding to the node.
202202
actions, // optional: An array of extra action on the node (such as displaying an info icon or any custom icons/elements)
203+
dataset, // optional: Allows data-* attributes to be set on the node and tag elements
203204
... // optional: Any extra properties that you'd like to receive during `onChange` event
204205
}
205206
```

src/dataset-utils.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const toKebabCase = (str) => str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()
2+
3+
const getDataset = (o = {}) => Object.keys(o).reduce((acc, cur) => {
4+
acc[`data-${toKebabCase(cur)}`] = o[cur]
5+
return acc
6+
}, {})
7+
8+
export {getDataset}

src/input/index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import cn from 'classnames/bind'
44
import debounce from 'lodash.debounce'
55
import Tag from '../tag'
66
import styles from './index.css'
7+
import { getDataset } from '../dataset-utils'
78

89
const cx = cn.bind(styles)
910

1011
const getTags = (tags = [], onDelete) => {
1112
return tags.map((tag, i) => {
12-
const {_id, label, tagClassName} = tag
13+
const {_id, label, tagClassName, dataset} = tag
1314
return (
14-
<li className={cx('tag-item', tagClassName)} key={`tag-${i}`}>
15+
<li className={cx('tag-item', tagClassName)} key={`tag-${i}`} {...getDataset(dataset)}>
1516
<Tag label={label} id={_id} onDelete={onDelete}/>
1617
</li>
1718
)

src/input/index.test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,18 @@ test('raises onchange', t => {
2828
wrapper.find('input').simulate('change', {target: {value: 'hello'}, persist: spy()})
2929
t.true(onChange.calledWith('hello'))
3030
})
31+
32+
test('should render data attributes', t => {
33+
const tags = [{_id: 'i1',
34+
label: 'l1',
35+
tagClassName: 'test',
36+
dataset: {
37+
first: 'john',
38+
last: 'smith'
39+
}}]
40+
41+
const wrapper = shallow(<Input tags={tags} />)
42+
43+
t.is(wrapper.find('.test').prop('data-first'), 'john')
44+
t.is(wrapper.find('.test').prop('data-last'), 'smith')
45+
})

src/tree-node/index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import isEmpty from '../isEmpty'
77
import NodeLabel from './node-label'
88

99
import styles from './index.css'
10+
import { getDataset } from '../dataset-utils'
1011

1112
const cx = cn.bind(styles)
1213

@@ -47,9 +48,10 @@ const TreeNode = props => {
4748
const { simpleSelect, keepTreeOnSearch, node, searchModeOn, onNodeToggle, onCheckboxChange } = props
4849
const liCx = getNodeCx(props)
4950
const toggleCx = getToggleCx(props)
51+
const style = keepTreeOnSearch || !searchModeOn ? { paddingLeft: `${node._depth * 20}px` } : {}
5052

5153
return (
52-
<li className={liCx} style={keepTreeOnSearch || !searchModeOn ? { paddingLeft: `${node._depth * 20}px` } : {}}>
54+
<li className={liCx} style={style} {...getDataset(node.dataset)}>
5355
<i className={toggleCx} onClick={() => onNodeToggle(node._id)} />
5456
<NodeLabel node={node} simpleSelect={simpleSelect} onCheckboxChange={onCheckboxChange} />
5557
{getNodeActions(props)}
@@ -68,7 +70,8 @@ TreeNode.propTypes = {
6870
label: PropTypes.string.isRequired,
6971
checked: PropTypes.bool,
7072
expanded: PropTypes.bool,
71-
disabled: PropTypes.bool
73+
disabled: PropTypes.bool,
74+
dataset: PropTypes.object
7275
}).isRequired,
7376
keepTreeOnSearch: PropTypes.bool,
7477
searchModeOn: PropTypes.bool,

src/tree-node/index.test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,20 @@ test('disable checkbox if the node has disabled status', t => {
7676

7777
t.true(wrapper.hasClass('disabled'))
7878
})
79+
80+
test('should render data attributes', t => {
81+
const node = {
82+
_id: '0-0-0',
83+
_parent: '0-0',
84+
label: 'item1-1-1',
85+
value: 'value1-1-1',
86+
dataset: {
87+
first: 'john',
88+
last: 'smith'
89+
}
90+
}
91+
92+
const wrapper = shallow(<TreeNode node={node} />)
93+
t.is(wrapper.prop('data-first'), 'john')
94+
t.is(wrapper.prop('data-last'), 'smith')
95+
})

0 commit comments

Comments
 (0)