I built a custom Component, and allow it to be re-rendered using as another component using BoxProps:
export function Label ({
children,
...boxProps
}: BoxProps) {
return (
<Box {...boxProps}>
{children}
</Box>
);
}
It's working well when I try to use the as={Button} props
<Label as={Button} >ID</Label>
But I cannot use the variant attribute available on Button
<Label as={Button} variant={'ghost'}>ID</Label>
^^^^^^^
Property 'variant' does not exist on type 'IntrinsicAttributes & BoxProps'.
Tried with as='button' ? variant will work with that combination.
Related
I have been trying to color the Autocomplete from MUI like the way i have described below based on some if conditions. Couldn’t find a way to do it.
Autocomplete component has renderTags property which takes an array of selected values and return chips. Therefore, you can customize the chip color (by using predefined theme colors via color prop or setting background color with sx prop) based on your condition:
<Autocomplete
multiple
renderTags={(value: readonly string[], getTagProps) =>
value.map((option: string, index: number) => (
<Chip
key={index}
variant="outlined"
label={option}
sx={{background: value === "A" ? 'red' : 'green'}}
/>
))
}
...other props
/>
you can try this
add MuiChip-label class in css
.MuiChip-label
{
color:#fff !important;
}
I a react-admin list view I want to display only records with a status value >2. status is a custom field.
The permanent filter section of the react-admin documentation (see https://marmelab.com/react-admin/List.html) only refers to static filters which checks for a specific field value like
export const PostList = (props) => (
<List {...props} filter={{ is_published: true }}>
...
</List>
);
but I'd like to pass a filter function like:
export const PostList = (props) => (
<List {...props} filter={()=>(status.id > 2)}>
...
</List>
);
Unfortunately this does not work. status is unknown and even if I return a static true or false it has no effect on filtering.
Is there another way or a workaround?
React-admin doesn't have any knowledge of how your API does "greater than" or "less than" queries (because there is no standard for that). The react-admin permanent filters are passed to your dataProvider, which passes them to your API.
So I advise you to use a special filter key in you list, as follows:
export const PostList = (props) => (
<List {...props} filter={{ status_id_gt: 2 }}>
...
</List>
);
Then, in your dataProvider, detect the usage of that filter, and transform it into whatever your API expects for a "greater than" filter.
I'd like to integrate react-mapbox-autocomplete with Antd's getFieldDecorator.
But it seems to Antd's getFieldDecorator only support for their own components.
Is there any way to use it for other packages like react-map-autocomplete?
Yes, it is possible to make getFieldDecorator to work with every custom component that is not an antd component.
As mentioned in the docs, you need to use the injected props from getFieldDecorator.
After wrapped by getFieldDecorator, value(or other property defined by valuePropName) onChange(or other property defined by trigger) props will be added to form controls.
As this is a very common question, here is some production code example:
Here we use a custom component SliderNumber with getFieldDecorator.
<Form.Item label={TOLERANCE.label}>
{getFieldDecorator(TOLERANCE.field)(<SliderNumber />)}
</Form.Item>
And within its implementation, we use the injected onChange and value from getFieldDecorator.
const SliderNumber = forwardRef(({ onChange, value: initial }, ref) => {
const [value, setValue] = useState(initial);
useEffect(() => {
onChange(value);
}, [onChange, value]);
return (
<FlexBox>
<FlexBox.Item span={SPAN}>
<Slider value={value} onChange={setValue} />
</FlexBox.Item>
<FlexBox.Item span={SPAN_REST}>
<InputNumber value={value} onChange={setValue} />
</FlexBox.Item>
</FlexBox>
);
});
Note that sometimes it is easier to just use ref without implementing the onChange like above.
Ant design has a HOC wrapper for forms that is implemented like this:
class View extends Component {
render() {
return ( <FormItem
{...formItemLayout}
label='Country'>
{getFieldDecorator('country', {
initialValue: Company && Company.country,
})(
<Select
showSearch={true}
optionFilterProp="children"
filterOption={(input: any, option: any) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
placeholder="Select a Country"
onChange={this.handleSelectChange}
>
{countrylist}
</Select>
)}
</FormItem>)
}
}
export default compose(
Form.create()
...
)(View)
In normal javascript, the this.handleSelectChange works fine, but I'm trying to migrate my project to typescript, and I'm getting:
Property 'handleSelectChange' does not exist on type View
I tried extending the interface, but I'm not getting it right. How do I get this to work?
The issue is that even though Form.create() was being called, the element isn't wrapping this - it is in a higher component. There is no need to call Form.create() here, just do it in the form component, and then pass down form as a prop. Then you can use
form.handleSelectChange
and that works.
I am using Material UI next library and currently I am using List component. Since the library is in beta, lot of its parameter names get changed. To solve this I am planning to write a wrapper around the required components so that things wont break. My list component :
<List dense>
<List className={classes.myListStyles}>
<ListItem disableGutters/>
</List>
</List>
How should I write the wrapper for the List(say myListWrapper) and ListItem so that the wrapper component can handle props and pass them to the actual MUI list component inside?
I had worked on MUI wrappers, writing my own library for a project. The implementation we are focusing, is to pass the props to inner/actual-MUI component from the our wrapper component. with manipulation. In case of wrapping props for abstraction.
Following is my approach to the solution:
import { List as MaterialList } from 'material-ui/List';
import { React } from 'react';
import { ListItem as MaterialListI } from 'material-ui/ListItem';
class List extends MaterialList {
constructor(props){
const propsToPass = {
prop1 : change(props.prop1),
...props
}
super(propsToPass);
}
};
class ListItem extends MaterialListItem {
const propsToPass = {
prop1 : change(props.prop1),
prop2 : change(props.prop2),
...props
}
super(propsToPass);
}
};
class App extends React.Component {
render () {
return (
<List prop='value' >
<ListItem prop1={somevalue1} prop2={somevalue2} />
<ListItem prop1={somevalue1} prop2={somevalue2} />
<ListItem prop1={somevalue1} prop2={somevalue2} />
</List>
)
}
};
Above code will allow following things to do with your component:
You can use the props with exact names, as used in Material UI.
You can manipulate/change/transform/reshape you props passed from outside.
If props to you wrapper components are passed with exactly same names as MUI is using, they will directly be sent to the inner component. (... operator.)
You can use Component with exact same name as material is using to avoid confusion.
Code is written according to advance JSX and JavaScript ES6 standards.
You have a space to manipulate your props to pass into the MUI Components.
You can also implement type checking using proptypes.
You can ask for any confusion/query.
You can write it like this:
const MyList = props => (
<List
{/*mention props values here*/}
propA={props.A}
propB={props.B}
>
{props.children}
</List>
)
const MyListItem = props => (
<ListItem
{/*mention props values here*/}
propA={props.A}
propB={props.B}
>
{props.children}
</ListItem>
)
Now you need to use MyList and MyListItem, decide the prop names for these component (as per your convenient), and inside these component map those values to actual Material-UI component properties.
Note:
If you are using the same prop names (same name as material-ui component expect) for your component then you can write like this also:
const MyList = ({children, ...rest}) => <div {...rest}>{children}</div>
const MyListItem = ({children, ...rest}) => <p {...rest}>{children}</p>
Check this example:
const A = props => <div>{props.children}</div>
const B = props => <p>{props.children}</p>
ReactDOM.render(
<A>
<A>
<B>Hello</B>
</A>
</A>,
document.getElementById('app')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app' />