React bootstrap typeahead clearButton icon (X) does not appear for a single selection - react-bootstrap-typeahead

I have tried selecting clearButton prop for a single selection input. However it does not work as expected. The clear (x) icon does not appear with a default selected input. It appears only once there is an event change, that is if I select some other input. My problem is that removing the input manually does not trigger a change in the selected value. Any pointers would be appreciated.
<Typeahead
clearButton
defaultInputValue={props.city}
options={props.cityOptions}
onChange={(selected) => handleCityFieldChange(selected[0], props)}
placeholder="Choose a city"
/>
Here's the handleCityFieldChange function:
handleCityFieldChange = (selected, props) => {
const newFieldValues = Object.assign({}, props.fieldValues, {"city": selected});
props.onChange(newFieldValues);
};

Use defaultSelected, not defaultInputValue:
<Typeahead
clearButton
defaultSelected={props.city}
options={props.cityOptions}
onChange={(selected) => handleCityFieldChange(selected[0], props)}
placeholder="Choose a city"
/>
The clear button only appears when there is a selection. defaultInputValue sets the value of the input, without actually selecting an option, which is why you weren't seeing the button.
Note: defaultSelected expects an array, so if props.city is an object, you'll need to pass [props.city].

Related

React-Bootstrap-Typeahead: Capture moment before setting selection into box (to allow conditional rejection)

In React-Boostrap-Typeahead, I need to capture the moment after the mouse has been clicked, but before the menu selection gets loaded into the Typeahead's box.
This is because I need to check items being selected, and for some of them, I need to display an alert with a Yes/No warning. Only if Yes is clicked can I proceed with setting that value into the box. Otherwise I need to reject the selection and keep it whatever it was prior to the mouse click.
I can't use onChange because by that point the selection is already in the box.
I can't use onInputChange because that is for typing rather than for menu selection. I need the post-menu-select, pre-box change.
If there are any workarounds please let me know.
You should be able to achieve what you're after using onChange:
const ref = useRef();
const [selected, setSelected] = useState([]);
return (
<Typeahead
id="example"
onChange={(selections) => {
if (!selections.length || window.confirm('Are you sure?')) {
return setSelected(selections);
}
ref.current.clear();
}}
options={options}
ref={ref}
selected={selected}
/>
);
Working example: https://codesandbox.io/s/objective-colden-w7ko9

How to deselect row when clicked outside the table? [used: Material-UI DataGrid]

I'm using Material-UI tables for showing my data, and I'm stuck when it comes to deselecting selected row.
So when user clicks outside the table, row should be deselected.
This is my code
const showData2 = (e,data) => {
console.log('selection',e)
}
<div style={{ height: 180, width: "100%", backgroundColor:'white' }}>
<DataGrid
rows={cases}
density='compact'
columns={columnsCases}
pageSize={3}
hideFooterSelectedRowCount={true}
rowHeight={40}
onRowSelected = {(e)=>{showData(e)}}
onSelectionChange= {(e)=>{showData2(e)}}
/>
</div>
Selection works perfectly but it seems impossible to deselect row when clicked outside the table
I would appreciate any idea and help.
Thank you!!
Use ClickAwayListener to detect if a click event happened outside of an element. It listens for clicks that occur somewhere in the document.
https://material-ui.com/components/click-away-listener/
Deselect Row Example using the ClickAwayListener with Typescript
Import GridRowId type in addition to whatever other types or components you need from data-grid
import { DataGrid, GridColDef, GridRowId } from '#material-ui/data-grid';
Set local state for the selectionModel prop on the DataGrid and init as an empty array.
const [selectionModel, setSelectionModel] = useState<GridRowId[]>([]);
Add DataGrid component as child of ClickAwayListener... plus your other DataGrid props.
<ClickAwayListener onClickAway={() => setSelectionModel([])}>
<DataGrid
{...otherProps}
checkboxSelection // <= works with or without checkbox selection
selectionModel={selectionModel}
onSelectionModelChange={({ selectionModel }) =>
setSelectionModel(selectionModel)
}
/>
</ClickAwayListener>
Of course you can just remove the types if you're not using Typescript.
Good Day,
Like #Omar EL KHAL said a ClickAwayListener works perfectly.
Step One: Define your onSelectionModelChange and handleClickAway function.
const handleSelection = (newSelection) => {
if (newSelection)
{
setSelectionModel(newSelection.selectionModel);
}
else
{
setSelectionModel(null);
}
}
const handleClickAway = () => {
handleSelection(null);
};
Step Two: Define your selectionModel as State
For this step I chose to set selectionModel in the component state to allow for other functions to set values.
const [selectionModel, setSelectionModel] = React.useState([]);
Step Three: Set the onSelectionModelChange and selectionModel props
Set the props props in the Data Grid as follows.
<ClickAwayListener onClickAway={handleClickAway}>
<DataGrid
onSelectionModelChange={handleSelection}
selectionModel={eventSelectionModel}
/>
</ClickAwayListener>
Once you save and let NPM do its thing you it should work.
I personally tested this on a single selection model but it should work with multiple as well.
P.S. I also did this with functional components and not classed components. The theory would be the same just instead of using useState you would use this.setState.
Happy Coding!
Gunny
There is no need for extra state. You could simply call the setSelectionModel function on the ClickAwayListener like so:
<ClickAwayListener onClickAway={() => apiRef.current.setSelectionModel([])}>
// your Data Grid
</ClickAwayListener>

Material UI IconButton onClick doesn't let to handle event

I installed "#material-ui/core": "^4.9.2" and "#material-ui/icons": "^4.9.1".
In my form i have several rows, each row has an add button and a remove button. I want the remove button to remove the row from it was clicked. It works fine with regular Button with a "-" character in it. But i want it fancy, so i replaced my Button from an IconButton, and imported the icons to use
import {AddCircleOutline,RemoveCircleOutlineOutlined} from "#material-ui/icons";
And my IconButton looks like this:
<IconButton
onClick={props.onRemoveClick}
className="align-self-center"
color="info"
size="sm"
disabled={props.index > 0 ? false : true}
<RemoveCircleOutlineOutlined/>
</IconButton>
When the IconButton is hit, the onClick method is called (i know because of logs in my console) but i can't handle the event because it is now undefined.
The funny thing is that if i click on the button area that doesn't correspond to the icon, it works. But obviously i need it to work in the whole area of the button.
It is not a binding issue because i already tested it.
Any ideas?
Props that are not cited in the documentation are inherited to their internal <EnhancedButton />, so you need to use a wrapper.
<IconButton
onClick={(e) => props.onRemoveClick(e)}
className="align-self-center"
color="info"
size="sm"
disabled={props.index > 0 ? false : true}
<RemoveCircleOutlineOutlined/>
</IconButton>
Well you gave an idea. Since i needed an index to identify the row's button, i sended the index through a paramater on the onClick method, like this:
onClick={e => props.onRemoveClick(props.index)}
In this way i didn't need to handle the event. I also had to bind my method on the constructor:
constructor(props) {
super(props);
this.handleRemoveClick = this.handleRemoveClick.bind(this);
}
Now i got the behaviour wanted
You can see the github ussue here. There is some problem with typescript definition files but we can work around it.
Solution
I tried to solve it like in the github issue but didn't work. So this works for me.
const onClick = (e: any) => {
// e is of type any so the compiler won't yell at you
}
<IconButton onClick={(e) => onClick(e)}>
I don't know the reason but using e.currentTarget helped me to get the button that I wanted and not the material icon inside it.
onClick={(e) => {
return console.log(e.currentTarget)
}}

SearchField in SAP UI5 does not render suggestions when "X" is clicked

I have implemented a SearchField. When I click on the "X" button, the value gets cleared. Cursor is blinking in the field, but the suggestions do not populate. If I click again in search field still do not populate.
I have to click somewhere else on the page and then again click in the search field again to ensure suggestions populate. How to handle the "X" ?
View.xml
<SearchField class="" suggestionItems="{path:'model>/names'}" id="names"
value="{model>/header/names}" suggest="onSuggest" enableSuggestions="true" width="90%">
<suggestionItems>
<SuggestionItem key="{model>UserId}" text="{order>LastName} , {order>FirstName}"/>
</suggestionItems>
</SearchField>
Controller.js
onSuggest: function (oEvent) {
var value = oEvent.getParameter("suggestValue");
this.oSF = this.getView().byId("name");
this.oSF.getBinding("suggestionItems")
this.oSF.suggest();
Have tried this attachEventOnce('dataReceived') solution?
BTW: using
this.oSF = oEvent.getSource()
instead of
this.oSF = this.getView().byId("name");
will keep you out of trouble with typos (names <=> name) ;-)

ReduxForm select value option is removed by filter, but option remains selected

I'm using Redux-form and I have a normal dropdown
there are 3 options in the list.
option 1
option 2
option 3
I select option 3.
I then go into my filter input field and type 1.
Now the list just contains option 1.
but option 3 is still selected in the form state.
How do I get the form to update and realize that that option isn't in the list anymore and go to default?
There's a couple ways I've though about doing it but not sure what's best.
I could write some state change logic in formReducer.plugin with an /CHANGE action type and filter field.
I could perhaps call onChange event on the select whenever I type in filter field.
I could always check in the select component render function if the current states selected value is in the list and if not, call a redux-form change action on the select to undefined.
r something better???
If you are using some component for your select, then you need to override the onChange prop to make sure your component gets the onChange event as well as the redux-form field input.
export const renderSelect = ({input, meta: { touched, error }, ...rest}) => {
return <Form.Select {...input} {...rest}
onChange={ (event, data) => { input.onChange(data.value);}}
/>
};
const MyFormComponent = (props) => {
const {brandData, productData, groupData} = props.optionsData;
return (
<Form>
<Field name='brandData' options={brandData} component={renderSelect}/>
<Field name='productData' options={productData} component={renderSelect}/>
<Field name='groupData' options={groupData} component={renderSelect}/>
</Form>
);
};
You can see a similar thing done in the redux-form example for integrating with 3rd party form components in their material-ui example.