Ant Design - How to remove arrow icon in Select component? - select

enter image description here
I'm using Select in Ant Design and don't know how to remove this icon.
Does anyone know the solution?
I try to edit some css and try config provider also but nothing work. Maybe i don't know the right way to do it
Hope you guys can help me

You can pass null to suffix prop in Select Component.
import { Select } from 'antd';
const App = () => {
return (
<Select
style={{ width: '200px' }}
suffixIcon={null}
options={[
{ value: '1', label: '1' },
{ value: '2', label: '2' }
]}
/>
);
};
export default App;

Related

leaflet map - adding a custom control similar to to the layers control but would like a different icon - defined by CSS

leaflet map - adding a custom control similar to to the layers control but would like a different icon - defined by CSS
I'm building a custom control on a leaflet map which I'd like to have work similarly to the leaflet layers control. I've copied the logic from the layers control to display the icon on the map and pop up the interface when the mouse hovers over it. It wasn't straight-forwards as the layers control is Javascript and I'm working in typescript. But it is working now, except for one small problem.
I cannot change the icon used by the layers tool since it is defined in CSS. The .SCSS styles I create can be used in the main form where the map is displayed, but not in the leaflet map itself. One brute force method would be to modify the leaflet source .css file and add my new css there. But I'm trying to avoid that.
Is there a way to get the map custom control to recognize CSS defined outside of leaflet?
In the code below, the line which creates the filter icon creates the class name leaflet-control-layers-toggle. This class defines the icon image. If I change this class to anything else, no icon is displayed.
this.filtersLink = L.DomUtil.create('a', className + '-toggle', this.container);
this.filtersLink.href = '#';
this.filtersLink.title = 'Filters';
/* ... */
private InitLayout() {
const className = 'leaflet-control-layers';
this.container = L.DomUtil.create('div', className);
this.container.style.backgroundColor = 'white';
this.container.setAttribute('aria-haspopup', 'true');
L.DomEvent.disableClickPropagation(this.container);
L.DomEvent.disableScrollPropagation(this.container);
this.section = L.DomUtil.create('section', className + '-list');
if (this.collapsed) {
this.map.on('click', this.CollapseDialog, this);
if (!L.Browser.android) {
L.DomEvent.on(this.container, {
mouseenter: this.ExpandDialog,
mouseleave: this.CollapseDialog
}, this);
}
}
this.filtersLink = L.DomUtil.create('a', className + '-toggle', this.container);
this.filtersLink.href = '#';
this.filtersLink.title = 'Filters';
if (L.Browser.touch) {
L.DomEvent.on(this.filtersLink, 'click', L.DomEvent.stop);
L.DomEvent.on(this.filtersLink, 'click', this.ExpandDialog, this);
} else {
L.DomEvent.on(this.filtersLink, 'focus', this.ExpandDialog, this);
}
this.AddLabel('Temporal');
this.AddRadioButton ( 'temporal01', 'temporal', 'Today', '1', false);
this.AddRadioButton ( 'temporal02', 'temporal', 'Yesterday', '2', false );
this.AddRadioButton ( 'temporal03', 'temporal', '7 Days', '3', true );
this.AddRadioButton ( 'temporal04', 'temporal', '30 Days', '4', false );
this.AddSeparator();
this.AddLabel('Severity');
this.AddCheckBox1 ( 'severity01', 'Major', '1', true );
this.AddCheckBox1 ( 'severity02', 'Minor', '2', true );
this.AddCheckBox1 ( 'severity03', 'Insignificant', '3', true );
this.AddSeparator();
this.AddLabel('Status');
this.AddCheckBox2 ( 'status01', 'Active', '1', true );
this.AddCheckBox2 ( 'status02', 'Reinspect', '2', true );
this.AddCheckBox2 ( 'status03', 'Reactivated', '3', true );
this.AddCheckBox2 ( 'status04', 'Closed', '4', false );
this.container.appendChild(this.section);
if (!this.collapsed) {
this.ExpandDialog();
}
}
Got it figured out - two ways to do this:
override with :ngdeep
add it to the styles.scss in the root of the project

Is it possible to get a set of checkboxes in react-hook-form to bind to a single array?

I am using react-hook-form with material-ui checkboxes. The following code works fine; however, each checkbox gets bound to its own field. In partial, when I hit submit, the output is something like this: {option1: true, option2: undefined, option3: true}
What I am hoping for is to get the output from all three checkboxes to bind into a single array, i.e. for the output to be something like this: {checkboxFieldName: [option1, option3]}.
I know that when using Formik, this is possible when the FormControlLabels of all checkboxes have the same names. So, just wondering if something similar is possible with react-hook-form.
Thank you in advance.
const options = [
{ key: 'option1', label: 'Option 1', val: 'option1' },
{ key: 'option2', label: 'Option 2', val: 'option2' },
{ key: 'option3', label: 'Option 3', val: 'option3' },
]
function App() {
const { handleSubmit, control } = useForm();
const onSubmit = data => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<FormControl>
<FormLabel>Check all suitable options</FormLabel>
<FormGroup>
{options.map((option) => (
<FormControlLabel
key={option.key}
name='checkboxFieldName'
value={option.val}
control={
<Controller
control={control}
name={option.key}
render={({ field: { onChange, value }}) => (
<Checkbox
checked={value}
onChange={e => onChange(e.target.checked)}
/>)}
/>}
label={option.label}
/>)
)}
</FormGroup>
</FormControl>
<Button type="submit">Save</Button>
</form>
);
}
I tried to do the same thing with Material UI but I ended up with more problems. Basically, you need to store selected checkboxes somewhere else (within an array) and set them to react-hook-form's state by using setValue function: https://react-hook-form.com/api/useform/setvalue/
Example: https://blog.logrocket.com/using-material-ui-with-react-hook-form/
If you don't want to do it manually, I would suggest using react-spectrum. It has a CheckboxGroup component and it stores all the selected values in an array: https://react-spectrum.adobe.com/react-spectrum/CheckboxGroup.html
Another solution is that you don't try to convert material-ui's object (checkboxFieldName: {option1: true, option2: undefined, option3: true}) into an array ({checkboxFieldName: [option1, option3]}) before submitting. Once you submit your form, you can convert your checkboxFieldName object into an array before passing the data to an API. Such as:
let checkboxFieldName = {option1: true, option2: undefined, option3: true}
let redefinedCheckboxFieldName = []
Object.entries(checkboxFieldName).forEach(([key, value]) => {
if(value){
redefinedCheckboxFieldName.push(key)
}
})

ReactDataGrid row selection does not work

I am trying to build data table using react and react-data-grid version "^7.0.0-canary.16",
The render method looks like this:
render() {
return (
<div className={"component"}>
<ReactDataGrid width={600} height={400}
rowKey="id"
columns={this.state.columns}
rows={this.state.rows}
onRowClick={this.onRowClick}
rowSelection={{
showCheckbox: true,
enableShiftSelect: true,
onRowsSelected: this.onRowsSelected,
onRowsDeselected: this.onRowsDeselected,
selectBy: {
indexes: this.state.selectedIndexes
}
}}
/>
</div>
)
}
So following the documentation on page https://adazzle.github.io/react-data-grid/docs/examples/row-selection
it should display checkbox in first column and when I select the checkbox it should call method this.onRowsSelected.
Alas, no checkbox is shown and no matter how I click the this.onRowsSelected method is never called.
On the other hand the method this.onRowClick is called, whenever I click somewhere in the table.
Does anyone have experience with this?
It seems to be showing the checkboxes with "react-data-grid": "6.1.0"
Although, I'm having issue with the checkboxes when we filter the data. The rowIdx changes and we lose context of that was previously selected. We want to make BE calls on selected Data. I tried changing it to use the row.id but no luck. It messes up the selection.
Here is a hook for managing the selection
import {useState} from 'react';
export const useRowSelection = () => {
const [selectedIndexes, setSelectedIndexes] = useState([]);
const onRowsSelected = rows => {
setSelectedIndexes(prevState => {
return prevState.concat(rows.map(r => r.rowIdx));
});
};
const onRowsDeselected = rows => {
let rowIndexes = rows.map(r => r.rowIdx);
setSelectedIndexes(prevState => {
return prevState.filter(i => rowIndexes.indexOf(i) === -1);
});
};
return {
selectedIndexes,
onRowsDeselected,
onRowsSelected,
};
};
Pass them to the RDG
const {selectedIndexes, onRowsDeselected, onRowsSelected} = useRowSelection();
const rowSelectionProps = enableRowSelection
? {
showCheckbox: true,
enableShiftSelect: true,
onRowsSelected: onRowsSelected,
onRowsDeselected: onRowsDeselected,
selectBy: {
indexes: selectedIndexes,
},
}
: undefined;
<ReactDataGrid
columns={columnDefinition}
getValidFilterValues={getFilterValues}
rowGetter={i => filteredData[i]}
rowsCount={filteredData.length}
onAddFilter={filter => handleOnAddFilter(filter)}
onClearFilters={() => handleOnCleanFilters()}
toolbar={toolbar}
contextMenu={contextMenu}
RowsContainer={ContextMenuTrigger}
rowSelection={rowSelectionProps}
rowKey="id"
/>

Autocomplete - How can I set a default value?

Does anyone know how to add a default value to the Autocomplete component?
The component have a dataSource, and I'd like to load the page with a specific item already selected(e.g. fill the text field with the selected item's text and it's value already set).
Does anyone knows how? Big thanks for any help <3
You can achieve this by setting the appropriate state in componentDidMount, for example:
componentDidMount() {
// load your items into your autocomplete
// set your default selected item
this.setState({ allItems: [itemYouWantToSet], selectedItem: item.name, selectedItemId: item.id }
}
render() {
return (
<Autocomplete
value={this.state.selectedItem}
items={this.state.allItems}
getItemValue={(item) => item.name}
onSelect={(value, item) => {
this.setState({ selectedItem: value, selectedItemId: value, allItems: [item] });
}}
/>
)
}
Then your item is correctly selected from the list of available options when it loads.
I tried all the above solutions and nothing worked. Perhaps the API has changed since then.
I finally figured out a solution. It's not so elegant, but in principle it makes sense. In my case the options are objects. I just had to set the "value" prop using the exact item from my options array. This way componentDidMount and getOptionSelected aren't needed.
Autocomplete is wrapped inside another component in our case. This is the main code:
class CTAutoComplete extends React.PureComponent {
getSelectedItem(){
const item = this.props.options.find((opt)=>{
if (opt.value == this.props.selectedValue)
return opt;
})
return item || {};
}
render() {
return (
<Autocomplete
id={this.props.id}
className={this.props.className}
style={{ width: '100%' }}
options={this.props.options}
getOptionLabel={this.props.getOptionLabel}
renderInput={params => (
<TextField {...params} label={this.props.label} variant="outlined" />
)}
onChange={this.props.onChange}
value={this.getSelectedItem()}
/>
);
}
}
IMPORTANT: When setting "value", you have to make sure to put the null case " || {} ", otherwise React complains you are changing from an uncontrolled to controlled component.
you can provide the defaultValue prop for AutoComplete.
<Autocomplete
multiple
id="tags-outlined"
options={this.state.categories}
getOptionLabel={(option) => option.category_name}
onChange={this.handleAutocomplete}
defaultValue={'yourDefaultStringValue'} //put your default value here. It should be an object of the categories array.
filterSelectedOptions
renderInput={(params) => (
<TextField
fullWidth
{...params}
variant="outlined"
label="Add Categories"
placeholder="Category"
required
/>
}
/>
This approach works for me (using hooks):
First of all define the options you need in a variable:
const genderOptions = [{ label: 'M' }, { label: 'V' }];
Second you can define a hook to store the selected value (for example store it in session storage for when the page refreshes, or use useState directly):
const age = useSessionStorage('age', '');
Next you can define your Autocomplete as follows (notice the default values in value and getOptionLabel, if you omit those you'll get those controlled to uncontrolled warnings):
<Autocomplete
id="id"
options={ageOptions}
getOptionLabel={option => option.label || ""}
value={ageOptions.find(v => v.label === age[0]) || {}} // since we have objects in our options array, this needs to be a object as well
onInputChange={(_, v) => age[1](v)}
renderInput={params => (
<TextField {...params} label="Leeftijd" variant="outlined" />
)}
/>
It is tricky specially in case of you are using along with filter option which load API on every filter. I was able to load initial value by setting up within state and onInputChange option.
Below is code that work for me or click below link for full working demo.
https://codesandbox.io/s/smoosh-brook-xgpkq?fontsize=14&hidenavigation=1&theme=dark
import React, { useState, useEffect } from "react";
import TextField from "#material-ui/core/TextField";
import Typography from "#material-ui/core/Typography";
import Autocomplete from "#material-ui/lab/Autocomplete";
export default function CreateEditStrategy({ match }) {
const [user, setUser] = useState({
_id: "32778",
name: "Magic User's Club!"
});
const [filter, setFilter] = useState("");
const [users, setUsers] = useState([]);
const [openAutoComplete, setOpenAutoComplete] = React.useState(false);
useEffect(() => {
(async () => {
//Will not filter anything for testing purpose
const response = await fetch(
`https://api.tvmaze.com/search/shows?q=${filter}`
);
const shows = await response.json();
setUsers(
shows.map((a, i) => {
return { _id: a.show.id, name: a.show.name };
})
);
})();
}, [filter]);
return (
<div>
<Typography variant="h6">Autocomplete</Typography>
<Autocomplete
open={openAutoComplete}
onOpen={() => setOpenAutoComplete(true)}
value={user}
inputValue={filter}
onClose={() => setOpenAutoComplete(false)}
onChange={(event, user) => {
if (user) setUser(user);
else setUser({ _id: "", name: "" });
}}
onInputChange={(event, newInputValue) => setFilter(newInputValue)}
getOptionSelected={(option, value) => option.name === value.name}
getOptionLabel={(option) => option.name}
options={users}
renderInput={(params) => (
<TextField
{...params}
label="Asynchronous"
variant="outlined"
InputProps={{
...params.InputProps
}}
/>
)}
/>
</div>
);
}
Call your component like this
<SelectCountryAutosuggest searchText="My Default Value" />
Make sure you apply the default value to state on class load
class SelectCountryAutosuggest extends React.Component {
state = {
value: this.props.searchText, //apply default value instead of ''
suggestions: [],
};
...
}
The api docs suggest the best approach in the current version (June 2022) is to use value and isOptionEqualToValue.
So for example, if I have a list of users and am choosing which user this thing is assigned to:
const [assignedTo, setAssignedTo] = useState(initialOption);
return (<Autocomplete
options={users.map((i) => ({
label: i.name,
value: i._id,
}))}
isOptionEqualToValue={(o, v) => o.value === v.id}
value={assignedTo}
onChange={(evt, val) => setAssignedTo(val)}
renderInput={(params) => (
<TextField {...params} label="Assigned To" />
)}
/>);
We can setup initial value through value property of Autocomplete component
<Autocomplete
fullWidth={true}
label={'Location'}
margin={'noraml'}
multiple={false}
name={'location'}
getOptionSelected={useCallback((option, value) => option.value === value.value)}
value={formValues.location === '' ? {label: ''} : {label: formValues.location}}
options={location}
ref={locationRef}
onChange={useCallback((e, v) => handleInputChange(e, v))}
/>
You can use the searchText property.
<AutoComplete searchText="example" ... />
Try this...
componentWillReceiveProps(nextProps) {
let value = nextProps.value
if (value) {
this.setState({
value: value
})
}
}
onUpdateInput worked for me - for anyone looking through all this as I was
Have you tried setting the searchText prop dynamically? You can pass the value you want to set to the Autocomplete component as the searchText prop. Something like,
<Autocomplete
searchText={this.state.input.name} // usually value={this.state.input.name}
/>
By default, it'll have the initial value set into the TextField of the Autocomplete component but when the user makes any modifications, it calls up the Autocomplete options depending on the dataSource prop.

CKEditor Link dialog modification

I am trying to add a drop down to CKEditor's link dialog. When selected, the drop down should insert corresponding class name to the link.
CKEDITOR.on( 'dialogDefinition', function( ev ) {
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
if ( dialogName == 'link' ) {
var infoTab = dialogDefinition.getContents( 'info' );
infoTab.add({
type: 'select',
label: 'Display link as a button',
id: 'buttonType',
'default': '',
items: [
['- Not button -', ''],
['Button one', 'btn-primary'],
['Button two', 'btn-success'],
['Button three', 'btn-danger']
],
commit: function(data) {
data.className = this.getValue();
}
});
}
});
I have a feeling commit function is not doing the job, but cannot figure out how to make it work. I saw a code that almost does the same thing as I want at http://www.lxg.de/code/simplify-ckeditors-link-dialog. I tried it and it does not work either.
I am using CKEditor 4.3.2.
I appreciate your help in advance.
If you console.log the data object in link dialog's onOk, you'll find quite a different hierarchy. Element classes are in data.advanced.advCSSClasses. But even if you decide to override (or extend) the value of this property in your commit, your string will be nuked by the original commit of advCSSClasses input field ("Advanced" tab) anyway. So the approach got to be a little bit different:
Always store the value of the select in data.
Override commit of advCSSClasses input field to consider stored value.
Remember to execute the original commit of advCSSClasses input.
Here we go:
CKEDITOR.on( 'dialogDefinition', function( ev ) {
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
if ( dialogName == 'link' ) {
var infoTab = dialogDefinition.getContents( 'info' ),
advTab = dialogDefinition.getContents( 'advanced' ),
advCSSClasses = advTab.get( 'advCSSClasses' );
infoTab.add( {
type: 'select',
label: 'Display link as a button',
id: 'buttonType',
'default': '',
items: [
['- Not button -', ''],
['Button one', 'btn-primary'],
['Button two', 'btn-success'],
['Button three', 'btn-danger']
],
commit: function( data ) {
data.buttonType = this.getValue();
}
});
var orgAdvCSSClassesCommit = advCSSClasses.commit;
advCSSClasses.commit = function( data ) {
orgAdvCSSClassesCommit.apply( this, arguments );
if ( data.buttonType && data.advanced.advCSSClasses.indexOf( data.buttonType ) == -1 )
data.advanced.advCSSClasses += ' ' + data.buttonType;
};
}
});
Now you got to only write a setup function which will detect whether one of your button classes is present to set a proper value of your select field once the dialog is open.