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

Adds disabling of inputs, minor bug fixes #36

Merged
merged 2 commits into from
Jan 21, 2019
Merged
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
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;
});
});
});