Skip to content

Commit

Permalink
Adds disabling of inputs, minor bug fixes (#36)
Browse files Browse the repository at this point in the history
Adds disabling of inputs, minor bug fixes
  • Loading branch information
grapoza committed Jan 21, 2019
1 parent cf5530b commit 97ea756
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 42 deletions.
38 changes: 20 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ The data passed to the treeview should be an array of nodes, where each node has
expanded: true,
selected: false,
input: {
value: false
value: false,
disabled: false
}
},
children: []
Expand All @@ -137,28 +138,29 @@ The data passed to the treeview should be an array of nodes, where each node has
state: {
expanded: true,
selected: false
// No input state here; to let complex radio button groupings work, state is bound to a tree-level property
// No input state here; to let complex radio button groupings work, state value is bound to a tree-level property. disabled, however, is valid here for radio buttons.
},
children: []
}
```

| Prop | Type | Description | Default value | Required |
|:------------------|:----------------|:---------------------------------------------------------|:----------------------------------|:---------|
| id | Number/String | An ID that uniquely identifies this node within the tree | - | Yes |
| label | String | The text to show in the treeview | - | Yes |
| expandable | Boolean | True to show a toggle for expanding nodes' subnode lists | `true` | |
| selectable | Boolean | True to allow the node to be selected* | `false` | |
| input | Object | Contains data specific to the node's `input` element | `null` | |
| input.type | String | The type of input; valid values are `checkbox` or `radio`| - | Yes** |
| input.name | String | The name attribute of the input; used with `radio` type | `'unspecifiedRadioName'` | |
| input.value | String | The value attribute of the input; used with `radio` type | `label`'s value*** | |
| state | Object | Contains the current state of the node | - | |
| state.expanded | Boolean | True if this node's subnode list is expanded | `false` | |
| state.selected | Boolean | True if the node is selected* | `false` | |
| state.input | Object | Contains any state related to the input field | `{}` for checkbox, otherwise - | |
| state.input.value | Boolean | Contains the value of the input | `false` for checkbox, otherwise - | |
| children | Array\<Object\> | The child nodes of this node | `[]` | |
| Prop | Type | Description | Default value | Required |
|:---------------------|:----------------|:---------------------------------------------------------|:----------------------------------|:---------|
| id | Number/String | An ID that uniquely identifies this node within the tree | - | Yes |
| label | String | The text to show in the treeview | - | Yes |
| expandable | Boolean | True to show a toggle for expanding nodes' subnode lists | `true` | |
| selectable | Boolean | True to allow the node to be selected* | `false` | |
| input | Object | Contains data specific to the node's `input` element | `null` | |
| input.type | String | The type of input; valid values are `checkbox` or `radio`| - | Yes** |
| input.name | String | The name attribute of the input; used with `radio` type | `'unspecifiedRadioName'` | |
| input.value | String | The value attribute of the input; used with `radio` type | `label`'s value*** | |
| state | Object | Contains the current state of the node | - | |
| state.expanded | Boolean | True if this node's subnode list is expanded | `false` | |
| state.selected | Boolean | True if the node is selected* | `false` | |
| state.input | Object | Contains any state related to the input field | `{}` for checkbox, otherwise - | |
| state.input.value | Boolean | Contains the value of the input | `false` for checkbox, otherwise - | |
| state.input.disabled | Boolean | True if the node's input field is disabled | `false` | |
| children | Array\<Object\> | The child nodes of this node | `[]` | |

\* Selection props are unused; see [#5](https://github.com/grapoza/vue-tree/issues/5).

Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ deploy_script:
if ($env:APPVEYOR_REPO_TAG -eq "true")
{
# npm_auth_token defined in the appveyor project on the site. https://www.appveyor.com/docs/lang/nodejs-iojs/#authenticating-npm-for-publishing-packages
"//registry.npmjs.org/:_authToken=$env:npm_auth_token`n" | out-file "$env:userprofile\.npmrc" -Encoding ASCII
"//registry.npmjs.org/:_authToken=$env:npm_auth_token`n" | out-file (Join-Path $Home "/.npmrc") -Encoding ASCII
npm publish package/ --access public
}
...
9 changes: 6 additions & 3 deletions demo/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export default [
expanded: false,
selected: false,
input: {
value: false
value: false,
disabled: false
}
},
children: []
Expand All @@ -30,7 +31,8 @@ export default [
expanded: true,
selected: false,
input: {
value: false
value: false,
disabled: false
}
},
children: [
Expand Down Expand Up @@ -58,7 +60,8 @@ export default [
expanded: false,
selected: false,
input: {
value: true
value: true,
disabled: true
}
},
children: [
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Yet another Vue treeview component.",
"author": "Gregg Rapoza <grapoza@gmail.com>",
"license": "MIT",
"version": "0.2.0",
"version": "0.3.0",
"browser": "vue-tree.umd.min.js",
"repository": {
"url": "https://github.com/grapoza/vue-tree",
Expand Down
2 changes: 1 addition & 1 deletion src/components/TreeView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
radioGroupValues: {
type: Object,
required: false,
default: {}
default: function () { return {}; }
}
},
data() {
Expand Down
28 changes: 22 additions & 6 deletions src/components/TreeViewNode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
:id="inputId"
:class="inputClass"
:type="model.input.type"
:disabled="model.state.input.disabled"
v-model="model.state.input.value"
@change="$_treeViewNode_onCheckboxChange" />

Expand All @@ -36,6 +37,7 @@
:type="model.input.type"
:name="model.input.name"
:value="model.input.value"
:disabled="model.state.input.disabled"
v-model="radioGroupValues[model.input.name]"
@change="$_treeViewNode_onRadioChange" />

Expand Down Expand Up @@ -119,19 +121,22 @@
return this.nodeId ? `${this.nodeId}-input` : null;
},
inputClass() {
if (!this.input || typeof this.input !== 'object') {
if (!this.model.input || typeof this.model.input !== 'object') {
return null;
}
let nodeInputClass = 'tree-view-node-self-input ';
switch (this.input.type) {
switch (this.model.input.type) {
case 'checkbox':
nodeInputClass += 'tree-view-node-self-checkbox';
break;
case 'radio':
nodeInputClass += 'tree-view-node-self-radio';
break;
default:
nodeInputClass = null;
break;
}
return nodeInputClass;
Expand Down Expand Up @@ -209,12 +214,20 @@
state.selected = false;
}
if (this.model.input && this.model.input.type === 'checkbox') {
if (this.model.input) {
if (state.input === null || typeof state.input !== 'object') {
state.input = {};
}
if (typeof state.input.value !== 'boolean') {
state.input.value = false;
if (state.input.disabled === null || typeof state.input.disabled !== 'boolean') {
state.input.disabled = false;
}
if (this.model.input.type === 'checkbox') {
if (typeof state.input.value !== 'boolean') {
state.input.value = false;
}
}
}
},
Expand Down Expand Up @@ -283,7 +296,10 @@
}
}
.tree-view-node-self-expander, .tree-view-node-self-checkbox, .tree-view-node-self-spacer {
.tree-view-node-self-expander,
.tree-view-node-self-checkbox,
.tree-view-node-self-radio,
.tree-view-node-self-spacer {
min-width: 1rem;
margin: 0;
}
Expand Down
36 changes: 24 additions & 12 deletions tests/data/node-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
* buttons will be added to the radioState parameter.
*
* The node spec's node string should be in the format:
* [eE]?[sS]?[cCrR]?
* `[eE]?[sS]?[cCrR!?]?`
* The presence of e, s or c|r indicate the node is expandable, selectable, and a checkbox or radio buttton
* respectively. If it is capitalized, then the related state should be True. In the case of inputs,
* the capitalization means the input will be selected.
* the capitalization means the input will be selected. The `!` indicates the input will be disabled.
*
* @param {Array<String, Array>} nodeSpec The node specification array.
* @param {Object} radioState An object in which the state of radio button groups is generated. Essentially an "out".
Expand All @@ -20,6 +20,7 @@ export function generateNodes(nodeSpec, radioState, baseId = "") {

nodeSpec.forEach(function (item, index) {
if (Array.isArray(item)) {
// Generate child nodes for Arrays
if (prevNode === null) {
return;
}
Expand All @@ -46,19 +47,30 @@ export function generateNodes(nodeSpec, radioState, baseId = "") {
children: []
};

if (lowerItem.includes('c')) {
prevNode.state.input = { value: item.includes('C') };
}
// Set up input state if needed
if (prevNode.input) {

// Disable inputs
prevNode.state.input = {
disabled: item.includes('!')
};

if (lowerItem.includes('r')) {
if (!radioState.hasOwnProperty(prevNode.input.name)) {
radioState[prevNode.input.name] = null;
// Set up checkbox state
if (lowerItem.includes('c')) {
prevNode.state.input.value = item.includes('C')
}

// Radio button selectedness can also be specified in the normal way by providing
// the radio button data to the TreeView's radioGroupValues prop.
if (item.includes('R')) {
radioState[prevNode.input.name] = prevNode.input.value;
// Set up the radiobutton state in the radioState
if (lowerItem.includes('r')) {
if (!radioState.hasOwnProperty(prevNode.input.name)) {
radioState[prevNode.input.name] = null;
}

// Radio button selectedness can also be specified in the normal way by providing
// the radio button data to the TreeView's radioGroupValues prop.
if (item.includes('R')) {
radioState[prevNode.input.name] = prevNode.input.value;
}
}
}

Expand Down
34 changes: 34 additions & 0 deletions tests/unit/TreeViewNode.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,38 @@ describe('TreeViewNode.vue', () => {
expect(wrapper.emitted().treeViewNodeDblclick).to.be.undefined;
});
});

describe('when a node\'s model is disabled', () => {

beforeEach(() => {
let radioState = {};
let model = generateNodes(['ces!'], radioState)[0];

console.debug(model);

wrapper = createWrapper({
model,
depth: 0,
treeId: 'tree',
radioGroupValues: radioState
});
});

it('has a disabled input', () => {
let input = wrapper.find('#' + wrapper.vm.inputId);
expect(input.element.disabled).to.be.true;
});
});

describe('when a node\'s model is not disabled', () => {

beforeEach(() => {
wrapper = createWrapper();
});

it('has an enabled input', () => {
let input = wrapper.find('#' + wrapper.vm.inputId);
expect(input.element.disabled).to.be.false;
});
});
});

0 comments on commit 97ea756

Please sign in to comment.