Skip to content

Commit

Permalink
Refactor #2075 - For AutoComplete
Browse files Browse the repository at this point in the history
  • Loading branch information
mertsincan committed Jun 1, 2021
1 parent bd3b32f commit 033f825
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 78 deletions.
15 changes: 7 additions & 8 deletions src/components/autocomplete/AutoComplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export class AutoComplete extends Component {
optionGroupTemplate: null,
forceSelection: false,
autoHighlight: false,
virtualScrollerOptions: null,
scrollHeight: '200px',
dropdown: false,
dropdownMode: 'blank',
Expand Down Expand Up @@ -86,6 +87,7 @@ export class AutoComplete extends Component {
optionGroupTemplate: PropTypes.any,
forceSelection: PropTypes.bool,
autoHighlight: PropTypes.bool,
virtualScrollerOptions: PropTypes.object,
scrollHeight: PropTypes.string,
dropdown: PropTypes.bool,
dropdownMode: PropTypes.string,
Expand Down Expand Up @@ -160,6 +162,7 @@ export class AutoComplete extends Component {
this.onPanelClick = this.onPanelClick.bind(this);

this.overlayRef = createRef();
this.virtualScrollerRef = createRef();
this.inputRef = createRef(this.props.inputRef);
}

Expand Down Expand Up @@ -377,7 +380,7 @@ export class AutoComplete extends Component {
}
}
else {
highlightItem = this.overlayRef.current.firstChild.firstChild;
highlightItem = DomHandler.findSingle(this.overlayRef.current, 'li');
if (DomHandler.hasClass(highlightItem, 'p-autocomplete-item-group')) {
highlightItem = this.findNextItem(highlightItem);
}
Expand Down Expand Up @@ -834,13 +837,9 @@ export class AutoComplete extends Component {
{input}
{loader}
{dropdown}
<AutoCompletePanel ref={this.overlayRef} suggestions={this.props.suggestions} field={this.props.field} listId={this.state.id + '_list'}
appendTo={this.props.appendTo} scrollHeight={this.props.scrollHeight} itemTemplate={this.props.itemTemplate} onItemClick={this.selectItem} ariaSelected={this.ariaSelected}
panelStyle={this.props.panelStyle} panelClassName={this.props.panelClassName} onClick={this.onPanelClick}
optionGroupLabel={this.props.optionGroupLabel} optionGroupChildren={this.props.optionGroupChildren} optionGroupTemplate={this.props.optionGroupTemplate}
getOptionGroupLabel={this.getOptionGroupLabel} getOptionGroupChildren={this.getOptionGroupChildren}
in={this.state.overlayVisible} onEnter={this.onOverlayEnter} onEntering={this.onOverlayEntering} onEntered={this.onOverlayEntered} onExit={this.onOverlayExit} onExited={this.onOverlayExited}
transitionOptions={this.props.transitionOptions} />
<AutoCompletePanel ref={this.overlayRef} virtualScrollerRef={this.virtualScrollerRef} {...this.props} listId={this.state.id + '_list'} onItemClick={this.selectItem} ariaSelected={this.ariaSelected}
onClick={this.onPanelClick} getOptionGroupLabel={this.getOptionGroupLabel} getOptionGroupChildren={this.getOptionGroupChildren}
in={this.state.overlayVisible} onEnter={this.onOverlayEnter} onEntering={this.onOverlayEntering} onEntered={this.onOverlayEntered} onExit={this.onOverlayExit} onExited={this.onOverlayExited} />
</span>
);
}
Expand Down
128 changes: 58 additions & 70 deletions src/components/autocomplete/AutoCompletePanel.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,13 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ObjectUtils from '../utils/ObjectUtils';
import { Ripple } from '../ripple/Ripple';
import { classNames } from '../utils/ClassNames';
import { CSSTransition } from '../transition/CSSTransition';
import { Portal } from '../portal/Portal';
import { VirtualScroller } from '../virtualscroller/VirtualScroller';

class AutoCompletePanelComponent extends Component {

static defaultProps = {
suggestions: null,
field: null,
appendTo: null,
optionGroupLabel: null,
optionGroupChildren: null,
optionGroupTemplate: null,
itemTemplate: null,
onItemClick: null,
scrollHeight: '200px',
listId: null,
ariaSelected: null,
panelClassName: null,
panelStyle: null,
forwardRef: null,
onClick: null,
getOptionGroupLabel: null,
getOptionGroupChildren: null
}

static propTypes = {
suggestions: PropTypes.array,
field: PropTypes.string,
appendTo: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
optionGroupLabel: PropTypes.string,
optionGroupChildren: PropTypes.string,
optionGroupTemplate: PropTypes.any,
itemTemplate: PropTypes.any,
onItemClick: PropTypes.func,
scrollHeight: PropTypes.string,
listId: PropTypes.any,
ariaSelected: PropTypes.any,
panelClassName: PropTypes.string,
panelStyle: PropTypes.object,
forwardRef: PropTypes.any,
onClick: PropTypes.func,
getOptionGroupLabel: PropTypes.func,
getOptionGroupChildren: PropTypes.func
};

getOptionGroupRenderKey(optionGroup) {
return ObjectUtils.resolveFieldData(optionGroup, this.props.optionGroupLabel);
}
Expand All @@ -68,53 +28,81 @@ class AutoCompletePanelComponent extends Component {
)
}

renderItem(suggestion, index) {
if (this.props.optionGroupLabel) {
const groupContent = this.props.optionGroupTemplate ? ObjectUtils.getJSXElement(this.props.optionGroupTemplate, suggestion, index) : this.props.getOptionGroupLabel(suggestion);
const groupChildrenContent = this.renderGroupChildren(suggestion, index);
const key = index + '_' + this.getOptionGroupRenderKey(suggestion);

return (
<React.Fragment key={key}>
<li className="p-autocomplete-item-group">
{groupContent}
</li>
{groupChildrenContent}
</React.Fragment>
)
}
else {
let itemContent = this.props.itemTemplate ? ObjectUtils.getJSXElement(this.props.itemTemplate, suggestion, index) : this.props.field ? ObjectUtils.resolveFieldData(suggestion, this.props.field) : suggestion;

return (
<li key={index + '_item'} role="option" aria-selected={this.props.ariaSelected === suggestion} className="p-autocomplete-item" onClick={(e) => this.props.onItemClick(e, suggestion)}>
{itemContent}
<Ripple />
</li>
);
}
}

renderItems() {
if (this.props.suggestions) {
if (this.props.optionGroupLabel) {
return this.props.suggestions.map((suggestion, i) => {
const groupContent = this.props.optionGroupTemplate ? ObjectUtils.getJSXElement(this.props.optionGroupTemplate, suggestion, i) : this.props.getOptionGroupLabel(suggestion);
const groupChildrenContent = this.renderGroupChildren(suggestion, i);
const key = i + '_' + this.getOptionGroupRenderKey(suggestion);
return this.props.suggestions.map((suggestion, index) => this.renderItem(suggestion, index));
}

return (
<React.Fragment key={key}>
<li className="p-autocomplete-item-group">
{groupContent}
</li>
{groupChildrenContent}
</React.Fragment>
)
});
}
else {
return this.props.suggestions.map((suggestion, index) => {
let itemContent = this.props.itemTemplate ? ObjectUtils.getJSXElement(this.props.itemTemplate, suggestion, index) : this.props.field ? ObjectUtils.resolveFieldData(suggestion, this.props.field) : suggestion;
return null;
}

renderContent() {
if (this.props.virtualScrollerOptions) {
const virtualScrollerProps = { ...this.props.virtualScrollerOptions, ...{
style: {...this.props.virtualScrollerOptions.style, ...{ height: this.props.scrollHeight || 'auto' }},
items: this.props.suggestions,
itemTemplate: (item, options) => item && this.renderItem(item, options.index),
contentTemplate: (options) => {
const className = classNames('p-autocomplete-items', options.className);

return (
<li key={index + '_item'} role="option" aria-selected={this.props.ariaSelected === suggestion} className="p-autocomplete-item" onClick={(e) => this.props.onItemClick(e, suggestion)}>
{itemContent}
<Ripple />
</li>
<ul ref={options.ref} className={className} role="listbox" id={this.props.listId}>
{options.children}
</ul>
);
});
}
}
}};

return <VirtualScroller ref={this.props.virtualScrollerRef} {...virtualScrollerProps} />;
}
else {
const items = this.renderItems();

return null;
return (
<ul className="p-autocomplete-items" role="listbox" id={this.props.listId}>
{items}
</ul>
);
}
}

renderElement() {
const panelClassName = classNames('p-autocomplete-panel p-component', this.props.panelClassName);
const panelStyle = { maxHeight: this.props.scrollHeight, ...this.props.panelStyle };
let items = this.renderItems();
const content = this.renderContent();

return (
<CSSTransition nodeRef={this.props.forwardRef} classNames="p-connected-overlay" in={this.props.in} timeout={{ enter: 120, exit: 100 }} options={this.props.transitionOptions}
unmountOnExit onEnter={this.props.onEnter} onEntering={this.props.onEntering} onEntered={this.props.onEntered} onExit={this.props.onExit} onExited={this.props.onExited}>
<div ref={this.props.forwardRef} className={panelClassName} style={panelStyle} onClick={this.props.onClick}>
<ul className="p-autocomplete-items" role="listbox" id={this.props.listId} style={{ maxHeight: this.props.scrollHeight || 'auto' }}>
{items}
</ul>
{content}
</div>
</CSSTransition>
);
Expand Down

0 comments on commit 033f825

Please sign in to comment.