Skip to content

Commit a100034

Browse files
committed
fix: Prefix instance id in case of custom node id
Fixes #315
1 parent f4ce73c commit a100034

File tree

5 files changed

+58
-19
lines changed

5 files changed

+58
-19
lines changed

src/tag/index.js

+3-6
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import React, { PureComponent } from 'react'
33

44
import './index.css'
55

6-
export const getTagId = id => `${id}_tag`
7-
86
class Tag extends PureComponent {
97
static propTypes = {
108
id: PropTypes.string.isRequired,
@@ -37,10 +35,9 @@ class Tag extends PureComponent {
3735
}
3836

3937
render() {
40-
const { id, label, labelRemove = 'Remove', readOnly, disabled } = this.props
41-
42-
const tagId = getTagId(id)
43-
const buttonId = `${id}_button`
38+
const { label, labelRemove = 'Remove', readOnly, disabled, getDOMId } = this.props
39+
const tagId = getDOMId('tag')
40+
const buttonId = getDOMId('button')
4441
const className = ['tag-remove', readOnly && 'readOnly', disabled && 'disabled'].filter(Boolean).join(' ')
4542
const isDisabled = readOnly || disabled
4643

src/tags/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import './index.css'
77

88
const getTags = (tags = [], onDelete, readOnly, disabled, labelRemove) =>
99
tags.map(tag => {
10-
const { _id, label, tagClassName, dataset } = tag
10+
const { _id, label, tagClassName, dataset, getDOMId } = tag
1111
return (
1212
<li
1313
className={['tag-item', tagClassName].filter(Boolean).join(' ')}
@@ -21,6 +21,7 @@ const getTags = (tags = [], onDelete, readOnly, disabled, labelRemove) =>
2121
readOnly={readOnly}
2222
disabled={disabled}
2323
labelRemove={labelRemove}
24+
getDOMId={getDOMId}
2425
/>
2526
</li>
2627
)

src/tree-manager/flatten-tree.js

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import getPartialState from './getPartialState'
2+
import Node from './node'
23

34
import { isEmpty } from '../utils'
45

@@ -216,16 +217,8 @@ function walkNodes({
216217
_rv = { list: new Map(), defaultValues: [], singleSelectedNode: null },
217218
}) {
218219
const single = simple || radio
219-
nodes.forEach((node, i) => {
220-
node._depth = depth
221-
222-
if (parent) {
223-
node._id = node.id || `${parent._id}-${i}`
224-
node._parent = parent._id
225-
parent._children.push(node._id)
226-
} else {
227-
node._id = node.id || `${rootPrefixId ? `${rootPrefixId}-${i}` : i}`
228-
}
220+
nodes.forEach((n, i) => {
221+
const node = new Node({ rootPrefixId, depth, parent, index: i, ...n })
229222

230223
if (single && node.checked) {
231224
if (_rv.singleSelectedNode) {
@@ -261,6 +254,7 @@ function walkNodes({
261254
radio,
262255
showPartialState,
263256
hierarchical,
257+
rootPrefixId,
264258
_rv,
265259
})
266260

src/tree-manager/node.js

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* Represents a tree node (not DOM node) in the data tree.
3+
* It can have the following properties:
4+
*
5+
* id {string|optional} User defined id, comes from `data` passed to the component.
6+
* _id {string} Internal id, auto generated if `id` is not defined, otherwise set to `id`.
7+
* rootPrefixId {string} The id of the component's instance.
8+
* parent {Node} Parent node, if a child.
9+
* label {string|required} Checkbox label
10+
* value {string|required} Checkbox value
11+
* children {array<node>|optional} Array of child nodes
12+
* checked {bool|optional} Initial state of checkbox. if true, checkbox is selected and corresponding pill is rendered.
13+
* disabled {bool|optional} Selectable state of checkbox. if true, the checkbox is disabled and the node is not selectable.
14+
* expanded {bool|optional} If true, the node is expanded (children of children nodes are not expanded by default unless children nodes also have expanded: true).
15+
* className {string|optional} Additional css class for the node. This is helpful to style the nodes your way
16+
* tagClassName {string|optional} Css class for the corresponding tag. Use this to add custom style the pill corresponding to the node.
17+
* actions {array<object>|optional} An array of extra action on the node (such as displaying an info icon or any custom icons/elements)
18+
* dataset {object|optional} Allows data-* attributes to be set on the node and tag elements
19+
* isDefaultValue {bool|optional} Indicate if a node is a default value. When true, the dropdown will automatically select the node(s) when there is no other selected node. Can be used on more than one node.
20+
*
21+
*/
22+
export default class Node {
23+
constructor({ depth, rootPrefixId, parent, index, ...dataProps }) {
24+
// first copy all props coming from data
25+
Object.assign(this, dataProps)
26+
27+
// then assign basic ones
28+
this._depth = depth
29+
this.rootPrefixId = rootPrefixId
30+
31+
if (parent) {
32+
this._id = this.id || `${parent._id}-${index}`
33+
this._parent = parent._id
34+
parent._children.push(this._id)
35+
} else {
36+
this._id = this.id || `${rootPrefixId ? `${rootPrefixId}-${index}` : index}`
37+
}
38+
}
39+
40+
/**
41+
* Given an element, generate a DOM Id that's unique across instances
42+
*/
43+
getDOMId = element => {
44+
// if user has defined id, then ensure it's unique across instances
45+
if (this.id) return `${this.rootPrefixId}_${this.id}_${element}`
46+
return `${this._id}_${element}`
47+
}
48+
}

src/trigger/index.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React, { PureComponent } from 'react'
22
import PropTypes from 'prop-types'
33

44
import { getAriaLabel } from '../a11y'
5-
import { getTagId } from '../tag'
65

76
class Trigger extends PureComponent {
87
static propTypes = {
@@ -28,7 +27,7 @@ class Trigger extends PureComponent {
2827
labelledBy.push(triggerId)
2928
}
3029
tags.forEach(t => {
31-
labelledBy.push(getTagId(t._id))
30+
labelledBy.push(t.getDOMId('tag'))
3231
})
3332
labelAttributes = getAriaLabel(texts.label, labelledBy.join(' '))
3433
}

0 commit comments

Comments
 (0)