Skip to content

Commit

Permalink
Fixed #2098 - Add showSelectAll, selectAll and onSelectAll properties…
Browse files Browse the repository at this point in the history
… to MultiSelect
  • Loading branch information
mertsincan committed Jun 8, 2021
1 parent 9af5ae3 commit 6d85b8b
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 99 deletions.
1 change: 1 addition & 0 deletions src/components/multiselect/MultiSelect.css
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
flex-shrink: 0;
overflow: hidden;
position: relative;
margin-left: auto;
}

.p-multiselect-clear-icon {
Expand Down
9 changes: 8 additions & 1 deletion src/components/multiselect/MultiSelect.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ interface MultiSelectFilterParams {
filter: string;
}

interface MultiSelectAllParams {
originalEvent: React.SyntheticEvent;
checked: boolean;
}

export interface MultiSelectProps {
id?: string;
inputRef?: React.Ref<HTMLSelectElement>;
Expand Down Expand Up @@ -89,7 +94,6 @@ export interface MultiSelectProps {
tabIndex?: number;
dataKey?: string;
inputId?: string;
required?: boolean;
appendTo?: MultiSelectAppendToType;
tooltip?: string;
tooltipOptions?: TooltipOptions;
Expand All @@ -102,12 +106,15 @@ export interface MultiSelectProps {
panelHeaderTemplate?: MultiSelectPanelHeaderTemplateType;
panelFooterTemplate?: MultiSelectPanelFooterTemplateType;
transitionOptions?: object;
showSelectAll?: boolean;
selectAll?: boolean;
onChange?(e: MultiSelectChangeParams): void;
onFocus?(event: React.FocusEvent<HTMLInputElement>): void;
onBlur?(event: React.FocusEvent<HTMLInputElement>): void;
onShow?(): void;
onHide?(): void;
onFilter?(e: MultiSelectFilterParams): void;
onSelectAll?(e: MultiSelectAllParams): void;
}

export declare class MultiSelect extends React.Component<MultiSelectProps, any> { }
132 changes: 66 additions & 66 deletions src/components/multiselect/MultiSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export class MultiSelect extends Component {
tabIndex: 0,
dataKey: null,
inputId: null,
required: false,
appendTo: null,
tooltip: null,
tooltipOptions: null,
Expand All @@ -59,12 +58,15 @@ export class MultiSelect extends Component {
panelHeaderTemplate: null,
panelFooterTemplate: null,
transitionOptions: null,
showSelectAll: true,
selectAll: false,
onChange: null,
onFocus: null,
onBlur: null,
onShow: null,
onHide: null,
onFilter: null
onFilter: null,
onSelectAll: null
};

static propTypes = {
Expand Down Expand Up @@ -100,7 +102,6 @@ export class MultiSelect extends Component {
tabIndex: PropTypes.number,
dataKey: PropTypes.string,
inputId: PropTypes.string,
required: PropTypes.bool,
appendTo: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
tooltip: PropTypes.string,
tooltipOptions: PropTypes.object,
Expand All @@ -113,12 +114,15 @@ export class MultiSelect extends Component {
panelHeaderTemplate: PropTypes.any,
panelFooterTemplate: PropTypes.any,
transitionOptions: PropTypes.object,
showSelectAll: PropTypes.bool,
selectAll: PropTypes.bool,
onChange: PropTypes.func,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
onShow: PropTypes.func,
onHide: PropTypes.func,
onFilter: PropTypes.func
onFilter: PropTypes.func,
onSelectAll: PropTypes.func
};

constructor(props) {
Expand All @@ -137,7 +141,7 @@ export class MultiSelect extends Component {
this.onBlur = this.onBlur.bind(this);
this.onFilterInputChange = this.onFilterInputChange.bind(this);
this.onCloseClick = this.onCloseClick.bind(this);
this.onToggleAll = this.onToggleAll.bind(this);
this.onSelectAll = this.onSelectAll.bind(this);
this.onOverlayEnter = this.onOverlayEnter.bind(this);
this.onOverlayEntered = this.onOverlayEntered.bind(this);
this.onOverlayExit = this.onOverlayExit.bind(this);
Expand Down Expand Up @@ -226,7 +230,7 @@ export class MultiSelect extends Component {
//escape
case 27:
this.hide();
this.focusInput.focus();
this.inputRef.current.focus();
break;

default:
Expand Down Expand Up @@ -261,7 +265,7 @@ export class MultiSelect extends Component {
this.show();
}

this.focusInput.focus();
this.inputRef.current.focus();
}
}

Expand Down Expand Up @@ -306,33 +310,38 @@ export class MultiSelect extends Component {
}
}

onToggleAll(event) {
let value = null;
let visibleOptions = this.getVisibleOptions();

if (event.checked) {
value = [];

if (visibleOptions) {
const selectedOptions = visibleOptions.filter(option => this.isOptionDisabled(option) && this.isSelected(option));
value = selectedOptions.map(option => this.getOptionValue(option));
}
onSelectAll(event) {
if (this.props.onSelectAll) {
this.props.onSelectAll(event);
}
else if (visibleOptions) {
visibleOptions = visibleOptions.filter(option => !this.isOptionDisabled(option));
else {
let value = null;
let visibleOptions = this.getVisibleOptions();

if (this.props.optionGroupLabel) {
if (event.checked) {
value = [];
visibleOptions.forEach(optionGroup => value = [...value, ...this.getOptionGroupChildren(optionGroup).filter((option) => !this.isOptionDisabled(option)).map(option => this.getOptionValue(option))]);

if (visibleOptions) {
const selectedOptions = visibleOptions.filter(option => this.isOptionDisabled(option) && this.isSelected(option));
value = selectedOptions.map(option => this.getOptionValue(option));
}
}
else {
value = visibleOptions.map(option => this.getOptionValue(option));
else if (visibleOptions) {
visibleOptions = visibleOptions.filter(option => !this.isOptionDisabled(option));

if (this.props.optionGroupLabel) {
value = [];
visibleOptions.forEach(optionGroup => value = [...value, ...this.getOptionGroupChildren(optionGroup).filter((option) => !this.isOptionDisabled(option)).map(option => this.getOptionValue(option))]);
}
else {
value = visibleOptions.map(option => this.getOptionValue(option));
}

value = [...new Set([...value, ...(this.props.value||[])])];
}

value = [...new Set([...value, ...(this.props.value||[])])];
this.updateModel(event.originalEvent, value);
}

this.updateModel(event.originalEvent, value);
}

updateModel(event, value) {
Expand Down Expand Up @@ -425,7 +434,7 @@ export class MultiSelect extends Component {

onCloseClick(event) {
this.hide();
this.focusInput.focus();
this.inputRef.current.focus();
event.preventDefault();
event.stopPropagation();
}
Expand Down Expand Up @@ -644,27 +653,32 @@ export class MultiSelect extends Component {
}

isAllSelected() {
let visibleOptions = this.getVisibleOptions();
if (visibleOptions.length === 0) {
return false;
if (this.props.onSelectAll) {
return this.props.selectAll;
}
else {
let visibleOptions = this.getVisibleOptions();
if (visibleOptions.length === 0) {
return false;
}

visibleOptions = visibleOptions.filter((option) => !this.isOptionDisabled(option));
visibleOptions = visibleOptions.filter((option) => !this.isOptionDisabled(option));

if (this.props.optionGroupLabel) {
for (let optionGroup of visibleOptions) {
const visibleOptionsGroupChildren = this.getOptionGroupChildren(optionGroup).filter((option) => !this.isOptionDisabled(option));
for (let option of visibleOptionsGroupChildren) {
if (!this.isSelected(option)) {
return false;
if (this.props.optionGroupLabel) {
for (let optionGroup of visibleOptions) {
const visibleOptionsGroupChildren = this.getOptionGroupChildren(optionGroup).filter((option) => !this.isOptionDisabled(option));
for (let option of visibleOptionsGroupChildren) {
if (!this.isSelected(option)) {
return false;
}
}
}
}
}
else {
for (let option of visibleOptions) {
if (!this.isSelected(option)) {
return false;
else {
for (let option of visibleOptions) {
if (!this.isSelected(option)) {
return false;
}
}
}
}
Expand Down Expand Up @@ -769,15 +783,15 @@ export class MultiSelect extends Component {
let label;

if (!this.isEmpty() && !this.props.fixedPlaceholder) {
label = '';
for (let i = 0; i < this.props.value.length; i++) {
if (i !== 0) {
label += ',';
if (this.props.value.length <= this.props.maxSelectedLabels) {
label = '';
for (let i = 0; i < this.props.value.length; i++) {
if (i !== 0) {
label += ',';
}
label += this.getLabelByValue(this.props.value[i]);
}
label += this.getLabelByValue(this.props.value[i]);
}

if (this.props.value.length <= this.props.maxSelectedLabels) {
return label;
}
else {
Expand Down Expand Up @@ -862,18 +876,6 @@ export class MultiSelect extends Component {
);
}

renderHiddenSelect() {
let selectedOptions = this.props.value ? this.props.value.map((option, index) => <option key={this.getOptionLabel(option) + '_' + index} value={this.getOptionValue(option)}></option>) : null;

return (
<div className="p-hidden-accessible p-multiselect-hidden-select">
<select ref={this.inputRef} required={this.props.required} name={this.props.name} tabIndex={-1} aria-hidden="true" multiple>
{selectedOptions}
</select>
</div>
);
}

render() {
let className = classNames('p-multiselect p-component p-inputwrapper', {
'p-multiselect-chip': this.props.display === 'chip',
Expand All @@ -887,13 +889,11 @@ export class MultiSelect extends Component {

let label = this.renderLabel();
let clearIcon = this.renderClearIcon();
let hiddenSelect = this.renderHiddenSelect();

return (
<div id={this.props.id} className={className} onClick={this.onClick} ref={el => this.container = el} style={this.props.style}>
{hiddenSelect}
<div className="p-hidden-accessible">
<input ref={el => this.focusInput = el} id={this.props.inputId} readOnly type="text" onFocus={this.onFocus} onBlur={this.onBlur} onKeyDown={this.onKeyDown}
<input ref={this.inputRef} id={this.props.inputId} name={this.props.name} readOnly type="text" onFocus={this.onFocus} onBlur={this.onBlur} onKeyDown={this.onKeyDown}
role="listbox" aria-haspopup="listbox" aria-labelledby={this.props.ariaLabelledBy} aria-expanded={this.state.overlayVisible} disabled={this.props.disabled} tabIndex={this.props.tabIndex} />
</div>
{label}
Expand All @@ -902,7 +902,7 @@ export class MultiSelect extends Component {
<span className="p-multiselect-trigger-icon pi pi-chevron-down p-c"></span>
</div>
<MultiSelectPanel ref={this.overlayRef} visibleOptions={visibleOptions} {...this.props} onClick={this.onPanelClick} onOverlayHide={this.hide}
filterValue={this.state.filter} hasFilter={this.hasFilter} onFilterInputChange={this.onFilterInputChange} onCloseClick={this.onCloseClick} onToggleAll={this.onToggleAll}
filterValue={this.state.filter} hasFilter={this.hasFilter} onFilterInputChange={this.onFilterInputChange} onCloseClick={this.onCloseClick} onSelectAll={this.onSelectAll}
getOptionLabel={this.getOptionLabel} getOptionRenderKey={this.getOptionRenderKey} isOptionDisabled={this.isOptionDisabled}
getOptionGroupChildren={this.getOptionGroupChildren} getOptionGroupLabel={this.getOptionGroupLabel} getOptionGroupRenderKey={this.getOptionGroupRenderKey}
isSelected={this.isSelected} getSelectedOptionIndex={this.getSelectedOptionIndex} isAllSelected={this.isAllSelected} onOptionSelect={this.onOptionSelect} allowOptionSelect={this.allowOptionSelect} onOptionKeyDown={this.onOptionKeyDown}
Expand Down
39 changes: 8 additions & 31 deletions src/components/multiselect/MultiSelectHeader.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,16 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { InputText } from '../inputtext/InputText';
import { Checkbox } from '../checkbox/Checkbox';
import { Ripple } from '../ripple/Ripple';
import ObjectUtils from '../utils/ObjectUtils';

export class MultiSelectHeader extends Component {

static defaultProps = {
filter: false,
filterValue: null,
filterPlaceholder: null,
onFilter: null,
onClose: null,
onToggleAll: null,
allSelected: false,
template: null
}

static propTypes = {
filter: PropTypes.bool,
filterValue: PropTypes.string,
filterPlaceholder: PropTypes.string,
allSelected: PropTypes.bool,
onFilter: PropTypes.func,
onClose: PropTypes.func,
onToggleAll: PropTypes.func,
template: PropTypes.any
}

constructor(props) {
super(props);

this.onFilter = this.onFilter.bind(this);
this.onToggleAll = this.onToggleAll.bind(this);
this.onSelectAll = this.onSelectAll.bind(this);
}

onFilter(event) {
Expand All @@ -45,11 +22,11 @@ export class MultiSelectHeader extends Component {
}
}

onToggleAll(event) {
if (this.props.onToggleAll) {
this.props.onToggleAll({
onSelectAll(event) {
if (this.props.onSelectAll) {
this.props.onSelectAll({
originalEvent: event,
checked: this.props.allSelected
checked: this.props.selectAll
});
}
}
Expand All @@ -70,7 +47,7 @@ export class MultiSelectHeader extends Component {

render() {
const filterElement = this.renderFilterElement();
const checkboxElement = <Checkbox checked={this.props.allSelected} onChange={this.onToggleAll} role="checkbox" aria-checked={this.props.allSelected} />;
const checkboxElement = this.props.showSelectAll && <Checkbox checked={this.props.selectAll} onChange={this.onSelectAll} role="checkbox" aria-checked={this.props.selectAll} />;
const closeElement = (
<button type="button" className="p-multiselect-close p-link" onClick={this.props.onClose}>
<span className="p-multiselect-close-icon pi pi-times"></span>
Expand All @@ -89,8 +66,8 @@ export class MultiSelectHeader extends Component {
const defaultOptions = {
className: 'p-multiselect-header',
checkboxElement,
checked: this.props.allSelected,
onChange: this.onToggleAll,
checked: this.props.selectAll,
onChange: this.onSelectAll,
filterElement,
closeElement,
closeElementClassName: 'p-multiselect-close p-link',
Expand Down
2 changes: 1 addition & 1 deletion src/components/multiselect/MultiSelectPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class MultiSelectPanelComponent extends Component {
renderHeader() {
return (
<MultiSelectHeader filter={this.props.filter} filterValue={this.props.filterValue} onFilter={this.onFilterInputChange} filterPlaceholder={this.props.filterPlaceholder}
onClose={this.props.onCloseClick} onToggleAll={this.props.onToggleAll} allSelected={this.props.isAllSelected()} template={this.props.panelHeaderTemplate} />
onClose={this.props.onCloseClick} showSelectAll={this.props.showSelectAll} selectAll={this.props.isAllSelected()} onSelectAll={this.props.onSelectAll} template={this.props.panelHeaderTemplate} />
);
}

Expand Down

0 comments on commit 6d85b8b

Please sign in to comment.