MUI5 React conditional textfield error color - javascript

I want to conditionally change the error color (warning orange and error red). I don't want to use useStyle because it's deprecated in mui5. Here is my code :
import { TextField as MuiTextField } from "#mui/material";
const TextField = styled(MuiTextField)(({ theme, isWarning }) => ({
"& .MuiOutlinedInput-root": {
"&.Mui-error": {
"& fieldset": {
borderColor: isWarning
? theme.palette.warning.main
: theme.palette.error.main,
},
"&:hover fieldset": {
borderColor: isWarning
? theme.palette.warning.main
: theme.palette.error.main,
},
"&.Mui-focused fieldset": {
borderColor: isWarning
? theme.palette.warning.main
: theme.palette.error.main,
},
},
},
}));
Then I use it like this :
<TextField
label="Description"
name="description"
value={this.state.description}
onChange={this.handleChange}
error={Boolean(errors?.description)}
isWarning={this.state.isWarning}
/>
It works but I got this error in the console :
Warning: React does not recognize the isWarning prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase iswarning instead. If you accidentally passed it from a parent component, remove it from the DOM element.
So I tried to use lowercase but I got this error :
Received true for a non-boolean attribute iswarning.
How can I do to remove this log ? Maybe there is another to change the color ?

Instead of using a style, you can change the color of the TextField to get the same effect. Make sure error is set to false or it will override the color to red.
<TextField
...
error={Boolean(errors?.description) && !this.state.isWarning}
color={this.state.isWarning ? "warning" : undefined}
/>
The color property docs can be found here.

Related

React formatting HTML element properties from multiple sources

I am iterating over state that holds the data for cards like
cards: [
{ id: 1, name: "p1", value: "Prize 1", imageSrc: "/path/to/image", bgColor: { background: "#FF6384", border: "4px solid #FF6384" }, isVisible: "" },
in my iteration, I am using a ternary to determine one of the classes like
<div className={`prize-card ${this.state.flipped === card ? "flipped" : ""} `} onClick={() => this.clickHandler(card)}>
I see how I can use the ternary to determine a second class on top of standard "prize-card", but how would I add even a third class based on the bgColor state? In a standard HTML element, I can just:
<div className={card.bgColor}>
But I can't figure out the syntax on how to add the {card.bgColor} to the rest of the className below... the bgColor below is wrapped in asterisks to show what I cannot add without errors.
<div className={ **{card.bgColor}**`prize-card ${this.state.flipped === card ? "flipped" : ""} `} onClick={() => this.clickHandler(card)}>
Any help is appreciated. Thank you in advance.

Propagate style props to React children and apply them to a CSS file

I am rendering component Dropdown which acts like html dropdown component, but is a collection of divs ordered and unordered lists. I am trying to pass styles to the className elements , which have dropdown.css file rendering the styles, but I am not sure how to target those specific elements all the way from the parent component.
How to target
div className="select-box-current"
with style={{ border: "1px solid #D4D4D4" }}
and
div className="select-box-list"
with
style={{
opacity: 1,
display: "inherit",
animationName: "none",
cursor: "pointer"
}}
The CodeSandblox is here -> https://codesandbox.io/s/weathered-wood-cf8u8?file=/src/App.js:481-614
So with React if you pass props that are the same name, it only select the one that was passed last. So with your two style props, it only would pass the last one. However, it probably isn't the best idea to use the name style anyway, since it isn't descriptive and also mirrors the actual HTML style attribute.
Give the two different styles unique names, in the App.js file:
<div className="App">
<Dropdown
inputName="viola"
list={[
{ yard_id: "1", yard_name: "Yard 1" },
{ yard_id: "2", yard_name: "Yard 2" }
]}
// this style is for className="select-box-current"
currentStyles={{ border: "1px solid #D4D4D4" }}
// this style is for className="select-box-list"
listStyles={{
opacity: 1,
display: "inherit",
animationName: "none",
cursor: "pointer"
}}
/>
</div>
Now we need to pass those two props through your component tree, the next file is the Dropdown.js file.
Before I get to passing the props, I want to comment about something that is wrong, that isn't entirely related.
export const Dropdown = ({ list, ...others }) => {
const copiedProps = {};
Object.keys(others).forEach((key) => {
// these are the props that need to get thru:
if ("style" === key || "className" === key) {
copiedProps[key] = others[key];
}
});
...
The copying of props, isn't necessary and the way that it is done is actually detrimental. If you want to specifically target a value in the incoming props, you can access it directly (ex props.myProp or in this case other.style) or destructuring assignment.
Since you are wanting to only pass the style (now listStyles and currentStyles) and the className I chose to assign them to a variable using the destructuring assignment.
export const Dropdown = ({
list,
currentStyles,
listStyles,
className,
...others
}) => { ... }
Now that we have those props, we want to pass it into your DropdownView which contains the actual elements you're wanting to target.
<DropdownView
dropdownItems={dropdownItems}
activeItem={activeItem}
hover={hover}
setActiveItem={(activeItem) => {
setActiveItem(activeItem);
}}
onMouseOver={(hover) => onMouseOver(hover)}
toggleList={() => toggleList(!hideList)}
hideList={hideList}
className={className}
currentStyles={currentStyles}
listStyles={listStyles}
/>
Okay, now we have the styles and classname where we want them. All you have to do is get the props like we did above, and then set them on the elements.
<div
className="select-box-current"
tabIndex="0"
autoFocus={true}
onClick={() => toggleList()}
style={currentStyles}
>...</div>
I forked the sandbox to include a working example. But node that I didn't set the use the className prop in the DropdowView since it wasn't clear what element would have that.
https://codesandbox.io/s/hardcore-sun-yyx0g?file=/src/DropdownView.jsx
I think instead of using them from the parent div you can directly use those styles to those elements like this. https://codesandbox.io/s/eloquent-lamport-3spzr?file=/src/App.js
But if you want to use those styles from the parent. Then you can pass them using specific name. Like this
<Dropdown
inputName="viola"
list={[
{ yard_id: "1", yard_name: "Yard 1" },
{ yard_id: "2", yard_name: "Yard 2" }
]}
// this style is for className="select-box-current"
selectBoxCurrentStyle={{ border: "1px solid #D4D4D4" }}
// this style is for className="select-box-list"
selectBoxListStyle={{
opacity: 1,
display: "inherit",
animationName: "none",
cursor: "pointer"
}}
/>
Here is the link https://codesandbox.io/s/damp-rain-cyhxb?file=/src/App.js:133-643

Nuxtjs : How to disappear the tooltip only when form input is valid

In the template below, the input disappears when fullName is true, but I wanna remove the tooltip only. Where should I fix it?
<a-tooltip placement="topRight" trigger="focus" :style="
fullName === true
? { display: 'none' }
: ''
">
<template slot="title">
<span>Please fill in your Fullname</span>
</template>
<a-input
#input="checkFullname"
:placeholder="$t('contact.placeholder.fullName')"
v-model="dropMessage.full_name"
:style="
fullName === false
? { backgroundColor: 'rgba(211,47,47,.025)' }
: ''
"
/>
</a-tooltip>
Using display: none to style your tooltip would cause the tooltip's default slot (the input) to also be hidden, but you don't have to resort to style bindings here.
<a-tooltip> has a v-model that can be set to false to hide the tooltip. For example, you could use a data prop (e.g., named tooltipVisible) as the v-model binding, and set it based on the user input in checkFullname():
<template>
<a-tooltip title="Enter John Doe" v-model="tooltipVisible">
<a-input #input="checkFullname" v-model="dropMessage.full_name" />
</a-tooltip>
</template>
<script>
export default {
data() {
return {
tooltipVisible: false,
}
},
methods: {
checkFullname() {
this.tooltipVisible = this.dropMessage.full_name !== 'John Doe'
},
},
}
</script>
demo

filterSelectedOptions in autocomplete Material UI Lab is not working with onChnage

When I am using autocomplete for getting the selected dates, The selected options is not getting filtered. Hence i am able to select multiple instance of the same data. Although when i remove OnChange prop its giving the result but now i am not able to update the state.
<Autocomplete
multiple
name="ClassSchedule"
onChange={(event, value) => setDays(value)}
ChipProps={{
style: {
backgroundColor: "#2EC5B6",
borderRadius: "5px",
color: "#fff",
fontFamily: "Source Sans Pro",
},
}}
id="tags-standard"
options={[
{ title: "sunday" },
{ title: "monday" },
{ title: "tuesday" },
{ title: "wednesday" },
{ title: "thursday" },
{ title: "friday" },
{ title: "saturday" },
]}
getOptionLabel={(option) => option.title}
renderInput={(params) => (
<CssTextField
{...params}
style={{
borderRadius: "10px",
backgroundColor: "#F5FCFB",
fontFamily: "Source Sans Pro",
}}
variant="outlined"
id="custom-css-outlined-input"
/>
)}
/>
According to Autocomplete doc:
value - any - The value of the autocomplete. The value must have reference equality with the option in order to be selected. You can customize the equality behavior with the getOptionSelected prop.
getOptionSelected - func - Used to determine if an option is selected, considering the current value. Uses strict equality by default.
So to know whether to exclude the selected value from the value in the list, you must implement getOptionSelected to check for the equality for exclusion, here is .title
<Autocomplete
...
getOptionSelected={(option, value) => option.title === value.title}
...
/>
Below is the forked codesandbox
Your onChange function needs to be enhanced. You have to set the value array same as given in options array. Both array needs to match. You were getting details from options--> Titles. then You must set it by creating a similar array on onChange. like set options--> Titles
Try My working Sandbox example here
To give you more knowledge on what is happening: the main reason behind why putting your onChange handler is causing the options to be populated again with all the days, is because your component is rerendered everytime you set the state for days versus when you weren't setting the state for days. I've found that Material UI Autocomplete default checking works with an array stored in a state versus the hardcoded options you have
options={availableDays} //state based
CodeSandBox: https://codesandbox.io/s/so-react-material-ui-autocomplete-h2unq?file=/src/App.js

I have to create button that will change the style of a text object in React Native App

I have a button, that change textValue of a text object, but I also have to change object's style
this.state = {
login_title: 'Initial Value',
isButtonPressed: true,
};
this.onPressButton= this.onPressButton.bind(this);
}
onPressButton() {
this.setState({
isButtonPressed : !this.state.isButtonPressed,
login_title : (this.state.isButtonPressed) ? 'Second Value' : 'Intial Value',
})
}
...
<Button onPress= {this.onPressButton}>
<ButtonText>Change Value</ButtonText>
<Text>{this.state.textValue}</Text>
In the <Text> widget you can define the style conditionally:
<Text style={this.state.isButtonPressed ? styles.style1 : styles.style2}>
{this.state.textValue}
</Text>
Of course, this means your style1 and style2 need to be defined.

Categories

Resources