I am using a Material UI button for my TODO react app. I just want my form to have a input field with submit button, but I want my submit Button to invisible so that user have a feeling that my form submits on clicking "Return" key.
import { TextField, Button } from '#material-ui/core';
<form>
<TextField
id="standard-basic"
label="Write a Todo"
variant="standard"
className="textField"
value={todoInput}
onChange={(e) => {
setTodoInput(e.target.value);
}} />
<Button
type="submit"
variant="contained"
onClick={addToDo}
className="buttonDisplay">
Display
</Button>
</form>
I added display: none; to my css still it does not disappears.
.buttonDisplay{
display: none;
}
Can someone tell me what is the issue with it.
If are looking for a way to submit form without a button, take a look at this.
export default function App() {
const [todoInput, setTodoInput] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
alert(todoInput);
};
return (
<form
onSubmit={(e) => {
handleSubmit(e);
}}
>
<TextField
id="standard-basic"
label="Write a Todo"
variant="standard"
className="textField"
value={todoInput}
onChange={(e) => {setTodoInput(e.target.value)}}
/>
</form>
);
}
onSubmit will be triggered when you press 'return' key
sandbox : https://codesandbox.io/s/polished-bush-uzi6e?file=/src/App.js
You can use different method to hide a button using CSS :
modify the opacity parameter
adjust the alpha color parameter
or just change the visibility aspect of your button
Here is a link that might help you using these elements :
Ways to hide elements in CSS
Related
Two buttons are rendered in my button component. Depending on the label, the button receives the class addButton or clearButton.
Button Component:
import './Button.css'
interface ButtonProps {
lable: string,
disabled: boolean,
onClick: MouseEventHandler<HTMLButtonElement>
}
export const Button: FunctionComponent<ButtonProps> = ({ lable, disabled, onClick}): ReactElement => {
let style: string = lable == 'ADD' ? 'addButton' : 'clearButton';
console.log(lable);
console.log(style);
return(
<div>
<button className= {`button ${style}`} type='button' disabled= { disabled } onClick= { onClick }>
{lable}
</button>
</div>
);
}
In the stylesheet Button.css are the two classes addButton and clearButton. Strangely, only the style class that is in second place is loaded. In this situation, the addButton receives its colour and the clearButton remains colourless. If I place the style class of the clearButton in second place in the stylesheet, it receives its colour and the addButton remains colourless.
Button.css
.clearButton {
background-color: #8c00ff;
}
.addButton {
background-color: #7ce0ff;
}
If I outsource both style classes to separate stylesheets, it works but this is not an elegant solution.
I would also like to understand the problem
I've execute your code, and it works, I think the problem is where you call the button you are not passing props to
change import type of button style
import styles from './Button.css';
return(
<div>
<button className={`button ${label === 'ADD' ? styles.addButton : styles.clearButton}`}>
{lable}
</button>
</div>
);
and reolace background-color to background
.clearButton {
background: #8c00ff;
}
.addButton {
background: #7ce0ff;
}
you can test code in this codesandbox project
I have a login page where I set border colors on focus and I want to keep the focus even when I'm clicking my eye password toggleI have attached a gif that shows how I loose my focus state when toggling my eye
One way to do it is to store a ref to the password input field, and call focus() on it in the eye's onClick handler:
import React, { useRef } from "react";
const Eye = ({ onClick }) => <span onClick={onClick}>eye</span>;
export default function App() {
const inputRef = useRef();
const handleEyeClick = () => {
if (inputRef.current) {
inputRef.current.focus();
}
};
return (
<div>
<input ref={inputRef} type="text" />
<Eye onClick={handleEyeClick} />
</div>
);
}
How do I change my cursor to be an icon when I click a button and then place that icon down on the second click, and become a regular cursor again? I'm working in React. All I have is that when I button is clicked, the global boolean clicked is turned to true.
Is this useful for what you need?
const [cursor, setCursor] = useState('crosshair');
const changeCursor = () => {
setCursor(prevState => {
if(prevState === 'crosshair'){
return 'pointer';
}
return 'crosshair';
});
}
return (
<div className="App" style={{ cursor: cursor }}>
<h2>Click to change mouse cursor</h2>
<input type="button" value="Change cursor"
onClick={changeCursor}
style={{ cursor: cursor }}
/>
</div>
);
I know how to style it with regular form inputs/selects/etc, but I have switched from using those to Formik Field, and the above doesn't work the same way.
<Formik
initialValues={{
example: ''
}}
validate={(values) => {
const errors = {};
if (!values.example) errors.example = 'Required';
return errors;
}}
onSubmit={this.handleSubmit}
render={formProps => {
return (
<Form>
<Field type='text' name='example' />
<ErrorMessage name='example' />
</Form>
)
}} />
So how would I change the border of the input from whatever it is normally to red if it is empty on submit?
Solution
You can style Field and ErrorMessage components provided by Formik just like you would style any other component in react. I created a working demo for you here: https://stackblitz.com/edit/react-formik-field-error-styles
Have a look. Continue reading for explanation.
Explanation
The simplest way would be to use style prop:
function getStyles(errors, fieldName) {
if (getIn(errors, fieldName)) {
return {
border: '1px solid red'
}
}
}
...
<Field style={getStyles(formProps.errors, 'example')} type='text' name='example' />
...
However, if you need manageable customizations, I would recommend you create a custom component. Field provides you with a component prop to which you can assign your own custom component like CustomInput or something like so:
function getStyles(errors, fieldName) {
if (getIn(errors, fieldName)) {
return {
border: '1px solid red'
}
}
}
function CustomInput({ field, form: { errors } }) {
return <div>
<input {...field} style={getStyles(errors, field.name)} />
<ErrorMessage name={field.name} />
</div>
}
...
<Field component={CustomInput} type="text" name="example" />
...
When i try the technique suggested in the accepted answer for ErrorMessage component using
<ErrorMessage name="propertyName" style={{ color: 'red'}}/>
it didn't work for me. It worked when i enclosed it inside another container though.
<div style={{ color: 'red'}}>
<ErrorMessage name="propertyName" />
</div>
Hope this helps someone.
FYI, the workaround that works for styling error fields (e.g. borders) is given here:
https://stackoverflow.com/a/66395574/1005607
Pretty astonishing that Formik doesn't provide this functionality out of the box, and you have to extend <Field> with custom code.
But in general, you're not supposed to use Formik's own <Field> component. Instead you should wire Formik to a component library like Material UI or React-Bootstrap which exposes isInvalid={..} or error={..} props on its components. That will allow you to style your controls properly. Here's an example of how to wire Formik to React-Bootstrap: https://react-bootstrap.github.io/components/forms/#forms-validation-libraries If you type into a control, you'll see how its style changes depending on errors.
I've built a Component using react-bootstrap based on #gene b. answer
It gets the meta field from the useField hook and passes eventual errors to the isInvalid prop:
isInvalid={meta.touched && meta.error}
Full component for text input:
import React from 'react';
import { useField } from 'formik';
import Form from 'react-bootstrap/Form';
export default function TextInput (props) {
const [field, meta] = useField(props);
return (
<Form.Group controlId={props.name}>
<Form.Label>{props.label}</Form.Label>
<Form.Control
name={props.name}
isInvalid={meta.touched && meta.error}
{...field}
/>
<Form.Control.Feedback type="invalid">
{meta.error}
</Form.Control.Feedback>
</Form.Group>
);
};
Usage
import { Form } from 'formik';
import TextInput from './textInput';
<Form>
<TextInput name="username" label="Username"/>
</Form>
It's worth mention that exists also the isValid prop that works exactly the opposite way, adding green flag on valid fields.
A Button component is generally comprised of the Text element wrapped with a TouchableHighlight (or other touchable). I'm trying to create a Button component styled using styled-components, but am having trouble getting my style to respond dynamically to props.
Button Component
Below, I've created a Button component similar to the Adapting based on props example found in the styled-component docs.
import React from 'react';
import { Text, TouchableHighlight } from 'react-native';
import styled from 'styled-components/native';
const colors = {
accent: '#911',
highlight: '#D22',
contrast: '#FFF',
}
const Label = styled.Text`
color: ${props => !props.outline ? colors.contrast : colors.accent};
font-weight: 700;
align-self: center;
padding: 10px;
`
const ButtonContainer = styled.TouchableHighlight`
background-color: ${props => props.outline ? colors.contrast : colors.accent};
width: 80%;
margin-top: 5px;
border-color: ${colors.accent};
border-width: 2px;
`
const Button = (props) => {
return (
<ButtonContainer
onPress={props.onPress}
underlayColor={colors.highlight}
>
<Label>
{props.children}
</Label>
</ButtonContainer>
);
};
export default Button;
Button Usage
After importing it, I'm using the button like this...
<Button
outline
onPress={() => console.log('pressed')}>
Press Me!
</Button>
Expected Result
And so, I would expect my button to look like this...
Actual Result
But instead it looks like this...
What I've done to troubleshoot so far
When I inspect using react-devtools, I can see that the outline prop is being passed down to the Button component.
But the prop is not passed down to any of it's children
The Passed Props part of the docs state, "styled-components pass on all their props", but I guess not all the way down?
My Question
What do I need to change so that I can dynamically style my Button based on it's props?
Here you have:
const Button = (props) => {
return (
<ButtonContainer underlayColor={colors.highlight}>
<Label>
{props.children}
</Label>
</ButtonContainer>
);
};
If ButtonContainer was a normal React component, you wouldn't expect the props passed to Button to be automatically passed to ButtonContainer. You'll have to do <ButtonContainer underlayColor={colors.highlight} {...props} /> to do it.
Actually ButtonContainer is a normal React component, the only difference is you pre-apply some styles using an HOC.
Also if you desugar this to a React.createElement call, you can see there's no way props can be passed automatically, because a Function's arguments don't get passed automatically to the function calls inside it.
const Button = (props) => {
return React.createElement(ButtonContainer, { underlayColor: colors.highlight }, ...);
};
It's nothing specific to styled-components. You just have to pass down the props yourself to ButtonContainer, as well as to Label.
So you'd rewrite your code to:
const Button = (props) => {
return (
<ButtonContainer underlayColor={colors.highlight} onPress={props.onPress} outline={props.outline}>
<Label outline={props.outline}>
{props.children}
</Label>
</ButtonContainer>
);
};
Technically a React component can pass down props to it's children, so ButtonContainer could pass them down to Label using React.Children and React.cloneElement APIs. But ButtonContainer doesn't do that for obvious reasons, e.g. you'd not want underlayColor and onPress to be passed to Label automatically. It would cause a lot of confusing bugs.