Skip to content

Commit

Permalink
Merge pull request #439 from dcos-labs/mp/feat/add-badge-to-input-on-…
Browse files Browse the repository at this point in the history
…blur

TextInputWithBadges update: adds input value as badge on blur
  • Loading branch information
mperrotti authored Dec 2, 2019
2 parents c86d77c + 96995be commit c379bb9
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 1 deletion.
19 changes: 19 additions & 0 deletions packages/textInput/components/TextInputWithBadges.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { TextInputWithIconProps } from "./TextInputWithIcon";
import { TextInputWithIcon } from "..";
import { BadgeAppearance } from "../../badge/components/badge";
import { StateChangeOptions } from "downshift";
import { InputAppearance } from "../../shared/types/inputAppearance";

export interface BadgeDatum {
value: string;
Expand All @@ -39,6 +40,7 @@ interface TextInputWithBadgesProps extends TextInputWithIconProps {
cb?: () => void
) => void;
badgeAppearance?: BadgeAppearance;
addBadgeOnBlur?: boolean;
}

export const getStringAsBadgeDatum = (
Expand All @@ -52,13 +54,20 @@ export class TextInputWithBadges extends TextInputWithIcon<
TextInputWithBadgesProps,
{}
> {
public static defaultProps: Partial<TextInputWithBadgesProps> = {
type: "text",
appearance: InputAppearance.Standard,
showInputLabel: true,
addBadgeOnBlur: true
};
private inputRef = React.createRef<HTMLInputElement>();

constructor(props) {
super(props);

this.handleKeyUp = this.handleKeyUp.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleBlur = this.handleBlur.bind(this);
this.handleTagAdd = this.handleTagAdd.bind(this);
this.handleTagDelete = this.handleTagDelete.bind(this);
}
Expand All @@ -69,10 +78,12 @@ export class TextInputWithBadges extends TextInputWithIcon<
badges,
onBadgeChange,
downshiftReset,
addBadgeOnBlur,
...inputProps
} = baseProps as TextInputWithBadgesProps;
inputProps.onKeyDown = this.handleKeyDown;
inputProps.onKeyUp = this.handleKeyUp;
inputProps.onBlur = this.handleBlur.bind(this, inputProps.onBlur);
inputProps.type = "text";
inputProps.ref = this.inputRef;
return inputProps;
Expand Down Expand Up @@ -195,6 +206,14 @@ export class TextInputWithBadges extends TextInputWithIcon<
}
}

private handleBlur(cb, e) {
cb(e); // calls the onBlur handler from the component this extends

if (this.props.addBadgeOnBlur) {
this.handleTagAdd(getStringAsBadgeDatum(e.target.value));
}
}

private onBadgeClose(clickedTag) {
this.handleTagDelete(clickedTag);
}
Expand Down
13 changes: 13 additions & 0 deletions packages/textInput/stories/TextInputWithBadges.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,19 @@ storiesOf("Forms/TextInputWithBadges", module)
)}
</TextInputWithBadgesStoryHelper>
))
.add("don't add badge on blur", () => (
<TextInputWithBadgesStoryHelper>
{({ badges, badgeChangeHandler }) => (
<TextInputWithBadges
id="noAddOnBlur"
inputLabel="Don't add badge on blur"
onBadgeChange={badgeChangeHandler}
badges={badges}
addBadgeOnBlur={false}
/>
)}
</TextInputWithBadgesStoryHelper>
))
.add("used w/ a Typeahead", () => (
<TextInputWithBadgesTypeaheadStoryHelper items={typeaheadItems}>
{({
Expand Down
46 changes: 45 additions & 1 deletion packages/textInput/tests/TextInputWithBadges.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,57 @@ describe("TextInputWithBadges", () => {
key: "Enter"
});

// TODO: change this if I decide not to "sanitize" the `value` string
expect(badgeChangeHandler).toHaveBeenCalledWith(
[getStringAsBadgeDatum(inputValue)],
getStringAsBadgeDatum(inputValue)
);
});

it("calls onBadgeChange with the badge data and input value when the input blurs", () => {
const badgeChangeHandler = jest.fn();
const inputValue = "some value";
const component = mount(
<TextInputWithBadges
id="appearance"
inputLabel="Appearance"
value={inputValue}
onBadgeChange={badgeChangeHandler}
/>
);

expect(badgeChangeHandler).not.toHaveBeenCalled();
component.find("input").simulate("focus");
component.find("input").simulate("blur");

expect(badgeChangeHandler).toHaveBeenCalledWith(
[getStringAsBadgeDatum(inputValue)],
getStringAsBadgeDatum(inputValue)
);
});

it("does not call onBadgeChange with the badge data and input value when the input blurs if addBadgeOnBlur=false", () => {
const badgeChangeHandler = jest.fn();
const inputValue = "some value";
const component = mount(
<TextInputWithBadges
id="appearance"
inputLabel="Appearance"
value={inputValue}
onBadgeChange={badgeChangeHandler}
addBadgeOnBlur={false}
/>
);

expect(badgeChangeHandler).not.toHaveBeenCalled();
component.find("input").simulate("focus");
component.find("input").simulate("blur");

expect(badgeChangeHandler).not.toHaveBeenCalledWith(
[getStringAsBadgeDatum(inputValue)],
getStringAsBadgeDatum(inputValue)
);
});

it("does not call onBadgeChange when keying enter if the input value is undefined", () => {
const badgeChangeHandler = jest.fn();
const component = mount(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ exports[`TextInputWithBadges renders badges with custom BadgeAppearance 1`] = `
}
<TextInputWithBadges
addBadgeOnBlur={true}
appearance="standard"
badges={
Array [
Expand Down Expand Up @@ -750,6 +751,7 @@ exports[`TextInputWithBadges renders empty 1`] = `
}
<TextInputWithBadges
addBadgeOnBlur={true}
appearance="standard"
id="empty"
inputLabel="empty"
Expand Down Expand Up @@ -1079,6 +1081,7 @@ exports[`TextInputWithBadges renders with badges 1`] = `
}
<TextInputWithBadges
addBadgeOnBlur={true}
appearance="standard"
badges={
Array [
Expand Down

0 comments on commit c379bb9

Please sign in to comment.