Skip to content

Commit 84c11b0

Browse files
authored
Added validation error feature to TagsInput (#749)
* added validation option * fixed lint tests * changed error on invalid tag prop name * show invalid tags error message anyway * fixes for Ethan code review
1 parent 1e9c919 commit 84c11b0

File tree

2 files changed

+74
-16
lines changed

2 files changed

+74
-16
lines changed

demo/src/screens/componentScreens/TagsInputScreen.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default class TagsInputScreen extends Component {
88
super(props);
99

1010
this.state = {
11-
tags: [{label: 'Amit'}, {label: 'Ethan'}],
11+
tags: [{label: 'Amit'}, {label: 'Ethan', invalid: true}],
1212
tags2: ['Tags', 'Input'],
1313
tags3: ['Non', 'Removable', 'Tags']
1414
};
@@ -36,6 +36,9 @@ export default class TagsInputScreen extends Component {
3636

3737
<TagsInput containerStyle={{marginBottom: 25}} placeholder="Enter Tags" tags={this.state.tags2}/>
3838

39+
<TagsInput containerStyle={{marginBottom: 25}} placeholder="Enter Tags" tags={this.state.tags}
40+
validationErrorMessage="error validation message" />
41+
3942
<TagsInput
4043
containerStyle={{marginBottom: 25}}
4144
placeholder="Editing disabled"

src/components/tagsInput/index.js

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default class TagsInput extends BaseComponent {
3030

3131
static propTypes = {
3232
/**
33-
* list of tags. can be string or custom object when implementing getLabel
33+
* list of tags. can be string boolean or custom object when implementing getLabel
3434
*/
3535
tags: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.object, PropTypes.string])),
3636
/**
@@ -53,6 +53,10 @@ export default class TagsInput extends BaseComponent {
5353
* callback for when pressing a tag in the following format (tagIndex, markedTagIndex) => {...}
5454
*/
5555
onTagPress: PropTypes.func,
56+
/**
57+
* validation message error appears when tag isn't validate
58+
*/
59+
validationErrorMessage: PropTypes.string,
5660
/**
5761
* if true, tags *removal* Ux won't be available
5862
*/
@@ -139,7 +143,6 @@ export default class TagsInput extends BaseComponent {
139143

140144
const newTag = _.isFunction(onCreateTag) ? onCreateTag(value) : value;
141145
const newTags = [...tags, newTag];
142-
143146
this.setState({
144147
value: '',
145148
tags: newTags
@@ -242,9 +245,17 @@ export default class TagsInput extends BaseComponent {
242245

243246
return (
244247
<View row centerV>
245-
{shouldMarkTag && <Image style={styles.removeIcon} source={Assets.icons.x}/>}
246-
<Text style={[styles.tagLabel, typography]} accessibilityLabel={`${label} tag`}>
247-
{shouldMarkTag ? 'Remove' : label}
248+
{shouldMarkTag && (
249+
<Image
250+
style={[styles.removeIcon, tag.invalid && styles.inValidTagRemoveIcon]}
251+
source={Assets.icons.x}
252+
/>)
253+
}
254+
<Text
255+
style={[tag.invalid ? (shouldMarkTag ? styles.errorMessageWhileMarked : styles.errorMessage)
256+
: styles.tagLabel, typography]} accessibilityLabel={`${label} tag`}
257+
>
258+
{!tag.invalid && shouldMarkTag ? 'Remove' : label}
248259
</Text>
249260
</View>
250261
);
@@ -255,6 +266,17 @@ export default class TagsInput extends BaseComponent {
255266
const {tagIndexToRemove} = this.state;
256267
const shouldMarkTag = tagIndexToRemove === index;
257268

269+
if (tag.invalid) {
270+
return (
271+
<View
272+
key={index}
273+
style={[styles.inValidTag, tagStyle, shouldMarkTag && styles.inValidMarkedTag]}
274+
>
275+
{this.renderLabel(tag, shouldMarkTag)}
276+
</View>
277+
);
278+
}
279+
258280
if (_.isFunction(renderTag)) {
259281
return renderTag(tag, index, shouldMarkTag, this.getLabel(tag));
260282
}
@@ -310,16 +332,24 @@ export default class TagsInput extends BaseComponent {
310332
}
311333

312334
render() {
313-
const {disableTagRemoval, containerStyle, hideUnderline} = this.getThemeProps();
335+
const {disableTagRemoval, containerStyle, hideUnderline, validationErrorMessage} = this.getThemeProps();
314336
const tagRenderFn = disableTagRemoval ? this.renderTag : this.renderTagWrapper;
315-
const {tags} = this.state;
337+
const {tags, tagIndexToRemove} = this.state;
316338

317339
return (
318340
<View style={[!hideUnderline && styles.withUnderline, containerStyle]}>
319341
<View style={styles.tagsList}>
320342
{_.map(tags, tagRenderFn)}
321343
{this.renderTextInput()}
322344
</View>
345+
{validationErrorMessage ?
346+
(
347+
<View>
348+
<Text style={[styles.errorMessage, tagIndexToRemove && styles.errorMessageWhileMarked]}>
349+
{validationErrorMessage}
350+
</Text>
351+
</View>
352+
) : null}
323353
</View>
324354
);
325355
}
@@ -336,6 +366,19 @@ export default class TagsInput extends BaseComponent {
336366
this.input.clear();
337367
}
338368
}
369+
const basicTagStyle = {
370+
borderRadius: BorderRadiuses.br100,
371+
paddingVertical: 4.5,
372+
paddingHorizontal: 12,
373+
marginRight: GUTTER_SPACING,
374+
marginVertical: GUTTER_SPACING / 2
375+
};
376+
377+
const basicIconStyle = {
378+
width: 10,
379+
height: 10,
380+
marginRight: 6
381+
};
339382

340383
const styles = StyleSheet.create({
341384
withUnderline: {
@@ -353,23 +396,35 @@ const styles = StyleSheet.create({
353396
},
354397
tag: {
355398
backgroundColor: Colors.blue30,
356-
borderRadius: BorderRadiuses.br100,
357-
paddingVertical: 4.5,
358-
paddingHorizontal: 12,
359-
marginRight: GUTTER_SPACING,
360-
marginVertical: GUTTER_SPACING / 2
399+
...basicTagStyle
400+
},
401+
inValidTag: {
402+
borderWidth: 1,
403+
borderColor: Colors.red30,
404+
...basicTagStyle
405+
},
406+
inValidMarkedTag: {
407+
borderColor: Colors.red10
361408
},
362409
tagMarked: {
363410
backgroundColor: Colors.dark10
364411
},
365412
removeIcon: {
366413
tintColor: Colors.white,
367-
width: 10,
368-
height: 10,
369-
marginRight: 6
414+
...basicIconStyle
415+
},
416+
inValidTagRemoveIcon: {
417+
tintColor: Colors.red10
370418
},
371419
tagLabel: {
372420
...Typography.text80,
373421
color: Colors.white
422+
},
423+
errorMessage: {
424+
...Typography.text80,
425+
color: Colors.red30
426+
},
427+
errorMessageWhileMarked: {
428+
color: Colors.red10
374429
}
375430
});

0 commit comments

Comments
 (0)