Skip to content

Commit

Permalink
added component functions to manipulate selected list
Browse files Browse the repository at this point in the history
changed defaultSelected to no longer modify the selected list after the first render
I accidentally fell into the trap of https://facebook.github.io/react/tips/props-in-getInitialState-as-anti-pattern.html
  • Loading branch information
trshafer committed Oct 16, 2015
1 parent 58f02e6 commit b154046
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 23 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,27 @@ Type: `Function`

A function to return the currently selected tokens.

#### tokenizer.addSelectedToken

Type: `Function`

A function to add a token to the selected list.
> This does not call `props.onTokenAdd(value)`
#### tokenizer.removeSelectedToken

Type: `Function`

A function to remove a token to the selected list.
> This does not call `props.onTokenRemove(value)`
#### tokenizer.setSelectedTokens

Type: `Function`

A function to remove all currently selected tokens and overwrite the selected list.
> This does not call `props.onTokenAdd(value) or props.onTokenRemove(value)`
## Developing

### Setting Up
Expand Down
42 changes: 27 additions & 15 deletions src/tokenizer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,6 @@ var TypeaheadTokenizer = React.createClass({
};
},

componentWillReceiveProps: function(nextProps){
// if we get new defaultProps, update selected
if (_arraysAreDifferent(this.props.defaultSelected, nextProps.defaultSelected)){
this.setState({selected: nextProps.defaultSelected.slice(0)})
}
},

focus: function(){
this.refs.typeahead.focus();
},
Expand All @@ -96,6 +89,30 @@ var TypeaheadTokenizer = React.createClass({
return this.state.selected;
},

setSelectedTokens: function(tokens){
this.setState({selected: tokens.slice(0)});
},

addSelectedToken: function(value){
if (this.state.selected.indexOf(value) != -1) {
return;
}
this.state.selected.push(value);
this.setState({selected: this.state.selected});
return true;
},

removeSelectedToken: function(value){
var index = this.state.selected.indexOf(value);
if (index == -1) {
return;
}

this.state.selected.splice(index, 1);
this.setState({selected: this.state.selected});
return true;
},

// TODO: Support initialized tokens
//
_renderTokens: function() {
Expand Down Expand Up @@ -147,25 +164,20 @@ var TypeaheadTokenizer = React.createClass({
},

_removeTokenForValue: function(value) {
var index = this.state.selected.indexOf(value);
if (index == -1) {
if (!this.removeSelectedToken(value)) {
return;
}

this.state.selected.splice(index, 1);
this.setState({selected: this.state.selected});
this.props.onTokenRemove(value);
return;
},

_addTokenForValue: function(value) {
if (this.state.selected.indexOf(value) != -1) {
if (!this.addSelectedToken(value)) {
return;
}
this.state.selected.push(value);
this.setState({selected: this.state.selected});
this.refs.typeahead.setEntryText("");
this.props.onTokenAdd(value);
return;
},

render: function() {
Expand Down
37 changes: 29 additions & 8 deletions test/tokenizer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,16 +168,37 @@ describe('TypeaheadTokenizer Component', function() {
this.component.focus();
assert.equal(this.component.refs.typeahead.focus.calledOnce, true);
});
});

it('should provide an exposed component function to get the selected tokens', function() {
simulateTokenInput(this.component, 'o');
var entry = this.component.refs.typeahead.refs.entry.getDOMNode();
TestUtils.Simulate.keyDown(entry, { keyCode: Keyevent.DOM_VK_DOWN });
TestUtils.Simulate.keyDown(entry, { keyCode: Keyevent.DOM_VK_RETURN });
it('should provide an exposed component function to get the selected tokens', function() {
simulateTokenInput(this.component, 'o');
var entry = this.component.refs.typeahead.refs.entry.getDOMNode();;
TestUtils.Simulate.keyDown(entry, { keyCode: Keyevent.DOM_VK_DOWN });
TestUtils.Simulate.keyDown(entry, { keyCode: Keyevent.DOM_VK_RETURN });

assert.equal(this.component.getSelectedTokens().length, 1);
assert.equal(this.component.getSelectedTokens()[0], "John");
assert.equal(this.component.getSelectedTokens().length, 1);
assert.equal(this.component.getSelectedTokens()[0], "John");
});

it('should provide an exposed component function to add tokens', function() {
this.component.addSelectedToken("John")
assert.equal(this.component.getSelectedTokens().length, 1);
assert.equal(this.component.getSelectedTokens()[0], "John");
});

it('should provide an exposed component function to remove tokens', function() {
this.component.addSelectedToken("John")
assert.equal(this.component.getSelectedTokens().length, 1);
this.component.removeSelectedToken("John")
assert.equal(this.component.getSelectedTokens().length, 0);
});

it('should provide an exposed component function to remove tokens', function() {
this.component.addSelectedToken("John")
this.component.setSelectedTokens(["Paul", "George"])
assert.equal(this.component.getSelectedTokens().length, 2);
assert.equal(this.component.getSelectedTokens()[0], "Paul");
assert.equal(this.component.getSelectedTokens()[1], "George");
});
});

describe('keyboard controls', function() {
Expand Down

0 comments on commit b154046

Please sign in to comment.