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

Add prop to mark field as required #154

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ onRemove(selectedList, removedItem) {
| `showArrow` | `bool` | `false` | For multiselect dropdown by default arrow wont show at the end, If required based on flag we can display
| `keepSearchTerm` | `bool` | `false` | Whether or not to keep the search value after selecting or removing an item
| `customCloseIcon` | `ReactNode or string` | `undefined` | Custom close icon and can be string or react component(Check demo for reference)
| `required` | `boolean` | `false` | Marks the input field as required to prevent form submission with missing values. **Form validation is required to ensure the field is populated before submitting.**
----


Expand Down
3 changes: 2 additions & 1 deletion src/multiselect/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ export interface IMultiselectProps {
hidePlaceholder?: boolean,
showArrow?: boolean,
keepSearchTerm?: boolean,
customCloseIcon?: React.ReactNode | string
customCloseIcon?: React.ReactNode | string,
required?: boolean
}
10 changes: 6 additions & 4 deletions src/multiselect/multiselect.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const closeIconTypes = {
};

export class Multiselect extends React.Component<IMultiselectProps, any> {
static defaultProps: { options: never[]; disablePreSelectedValues: boolean; selectedValues: never[]; isObject: boolean; displayValue: string; showCheckbox: boolean; selectionLimit: number; placeholder: string; groupBy: string; style: {}; emptyRecordMsg: string; onSelect: () => void; onRemove: () => void; closeIcon: string; singleSelect: boolean; caseSensitiveSearch: boolean; id: string; closeOnSelect: boolean; avoidHighlightFirstOption: boolean; hidePlaceholder: boolean; showArrow: boolean; keepSearchTerm: boolean; };
static defaultProps: { options: never[]; disablePreSelectedValues: boolean; selectedValues: never[]; isObject: boolean; displayValue: string; showCheckbox: boolean; selectionLimit: number; placeholder: string; groupBy: string; style: {}; emptyRecordMsg: string; onSelect: () => void; onRemove: () => void; closeIcon: string; singleSelect: boolean; caseSensitiveSearch: boolean; id: string; closeOnSelect: boolean; avoidHighlightFirstOption: boolean; hidePlaceholder: boolean; showArrow: boolean; keepSearchTerm: boolean; required: boolean; };
constructor(props) {
super(props);
this.state = {
Expand Down Expand Up @@ -505,9 +505,10 @@ export class Multiselect extends React.Component<IMultiselectProps, any> {

renderMultiselectContainer() {
const { inputValue, toggleOptionsList, selectedValues } = this.state;
const { placeholder, style, singleSelect, id, hidePlaceholder, disable, showArrow} = this.props;
const { placeholder, style, singleSelect, id, hidePlaceholder, disable, showArrow, required} = this.props;
const hasRequiredError = required && selectedValues.length === 0;
return (
<div className={`multiselect-container multiSelectContainer ${disable ? `disable_ms` : ''}`} id={id || 'multiselectContainerReact'} style={style['multiselectContainer']}>
<div className={`multiselect-container multiSelectContainer ${disable ? `disable_ms` : ''} ${hasRequiredError ? 'hasRequiredError' : ''}`} id={id || 'multiselectContainerReact'} style={style['multiselectContainer']}>
<div className={`search-wrapper searchWrapper ${singleSelect ? 'singleSelect' : ''}`}
ref={this.searchWrapper} style={style['searchBox']}
onClick={singleSelect ? this.toggelOptionList : () => {}}
Expand Down Expand Up @@ -572,5 +573,6 @@ Multiselect.defaultProps = {
hidePlaceholder: false,
showArrow: false,
keepSearchTerm: false,
customCloseIcon: ''
customCloseIcon: '',
required: false
};
8 changes: 8 additions & 0 deletions src/multiselect/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
min-height: 22px;
position: relative;
}
.hasRequiredError .searchWrapper {
border-color: red;
}
.hasRequiredError::after {
color: red;
content: "Please select a value";
font-style: italic;
}
.multiSelectContainer input {
border: none;
margin-top: 3px;
Expand Down
20 changes: 19 additions & 1 deletion stories/basic.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ export default {
} as Meta;

const Template: Story<IMultiselectProps> = (args) => <MultiSelect {...args} />;
const SubmitTemplate: Story<IMultiselectProps> = args => {
return (
<>
<form>
<MultiSelect {...args} />
<input type="submit" onSubmit={() => {}} />
</form>
</>
)
}

export const FlatArray = Template.bind({});
FlatArray.args = {
Expand Down Expand Up @@ -106,4 +116,12 @@ CustomCloseIcon.args = {
displayValue: 'key',
customCloseIcon: <>🍑</>,
selectedValues
};
};

export const RequiredField = SubmitTemplate.bind({});
RequiredField.args = {
options,
displayValue: 'key',
selectedValues,
required: true,
};