Skip to content

Commit b154046

Browse files
committed
added component functions to manipulate selected list
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
1 parent 58f02e6 commit b154046

File tree

3 files changed

+77
-23
lines changed

3 files changed

+77
-23
lines changed

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,27 @@ Type: `Function`
322322

323323
A function to return the currently selected tokens.
324324

325+
#### tokenizer.addSelectedToken
326+
327+
Type: `Function`
328+
329+
A function to add a token to the selected list.
330+
> This does not call `props.onTokenAdd(value)`
331+
332+
#### tokenizer.removeSelectedToken
333+
334+
Type: `Function`
335+
336+
A function to remove a token to the selected list.
337+
> This does not call `props.onTokenRemove(value)`
338+
339+
#### tokenizer.setSelectedTokens
340+
341+
Type: `Function`
342+
343+
A function to remove all currently selected tokens and overwrite the selected list.
344+
> This does not call `props.onTokenAdd(value) or props.onTokenRemove(value)`
345+
325346
## Developing
326347

327348
### Setting Up

src/tokenizer/index.js

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,6 @@ var TypeaheadTokenizer = React.createClass({
8181
};
8282
},
8383

84-
componentWillReceiveProps: function(nextProps){
85-
// if we get new defaultProps, update selected
86-
if (_arraysAreDifferent(this.props.defaultSelected, nextProps.defaultSelected)){
87-
this.setState({selected: nextProps.defaultSelected.slice(0)})
88-
}
89-
},
90-
9184
focus: function(){
9285
this.refs.typeahead.focus();
9386
},
@@ -96,6 +89,30 @@ var TypeaheadTokenizer = React.createClass({
9689
return this.state.selected;
9790
},
9891

92+
setSelectedTokens: function(tokens){
93+
this.setState({selected: tokens.slice(0)});
94+
},
95+
96+
addSelectedToken: function(value){
97+
if (this.state.selected.indexOf(value) != -1) {
98+
return;
99+
}
100+
this.state.selected.push(value);
101+
this.setState({selected: this.state.selected});
102+
return true;
103+
},
104+
105+
removeSelectedToken: function(value){
106+
var index = this.state.selected.indexOf(value);
107+
if (index == -1) {
108+
return;
109+
}
110+
111+
this.state.selected.splice(index, 1);
112+
this.setState({selected: this.state.selected});
113+
return true;
114+
},
115+
99116
// TODO: Support initialized tokens
100117
//
101118
_renderTokens: function() {
@@ -147,25 +164,20 @@ var TypeaheadTokenizer = React.createClass({
147164
},
148165

149166
_removeTokenForValue: function(value) {
150-
var index = this.state.selected.indexOf(value);
151-
if (index == -1) {
167+
if (!this.removeSelectedToken(value)) {
152168
return;
153169
}
154-
155-
this.state.selected.splice(index, 1);
156-
this.setState({selected: this.state.selected});
157170
this.props.onTokenRemove(value);
158171
return;
159172
},
160173

161174
_addTokenForValue: function(value) {
162-
if (this.state.selected.indexOf(value) != -1) {
175+
if (!this.addSelectedToken(value)) {
163176
return;
164177
}
165-
this.state.selected.push(value);
166-
this.setState({selected: this.state.selected});
167178
this.refs.typeahead.setEntryText("");
168179
this.props.onTokenAdd(value);
180+
return;
169181
},
170182

171183
render: function() {

test/tokenizer-test.js

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -168,16 +168,37 @@ describe('TypeaheadTokenizer Component', function() {
168168
this.component.focus();
169169
assert.equal(this.component.refs.typeahead.focus.calledOnce, true);
170170
});
171-
});
172171

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

179-
assert.equal(this.component.getSelectedTokens().length, 1);
180-
assert.equal(this.component.getSelectedTokens()[0], "John");
178+
assert.equal(this.component.getSelectedTokens().length, 1);
179+
assert.equal(this.component.getSelectedTokens()[0], "John");
180+
});
181+
182+
it('should provide an exposed component function to add tokens', function() {
183+
this.component.addSelectedToken("John")
184+
assert.equal(this.component.getSelectedTokens().length, 1);
185+
assert.equal(this.component.getSelectedTokens()[0], "John");
186+
});
187+
188+
it('should provide an exposed component function to remove tokens', function() {
189+
this.component.addSelectedToken("John")
190+
assert.equal(this.component.getSelectedTokens().length, 1);
191+
this.component.removeSelectedToken("John")
192+
assert.equal(this.component.getSelectedTokens().length, 0);
193+
});
194+
195+
it('should provide an exposed component function to remove tokens', function() {
196+
this.component.addSelectedToken("John")
197+
this.component.setSelectedTokens(["Paul", "George"])
198+
assert.equal(this.component.getSelectedTokens().length, 2);
199+
assert.equal(this.component.getSelectedTokens()[0], "Paul");
200+
assert.equal(this.component.getSelectedTokens()[1], "George");
201+
});
181202
});
182203

183204
describe('keyboard controls', function() {

0 commit comments

Comments
 (0)