How to show error on button click in React native? - validation

I am using 'react-native-material-textfield' and it working well, but I need to show error for empty field when clicking on submit button. I have searched lot-of but didn't find any solution.

Put the error message in your state and fill it with a message after clicking on the submit button, if your validation process fails.
render(){
return (
<View>
<TextField
{...props}
error={this.state.error}
errorColor={'red'}
onFocus={() => this.setState({error: ''})}
/>
<Button {...props} />
</View>)}
Check the example on the developers github repository.

According to the module documentation and examples, whenever your this.state.errors for each field is not empty, its error is shown. So your form should look like this:
class Form extends Component {
// ... Some required methods
onSubmit() {
let errors = {};
['firstname'] // This array should be filled with your fields names.
.forEach((name) => {
let value = this[name].value();
if (!value) {
errors[name] = 'Should not be empty'; // The error message when field is empty
}
});
this.setState({ errors });
}
render() {
let { errors = {}, data } = this.state;
return (
<View>
<TextField
value={data.firstname}
onChangeText={this.onChangeText}
error={errors.firstname}
/>
<Text onPress={this.onSubmit}>Submit</Text>
</View>
);
}
}

Related

How to hide columns in Datagrid based on filters values

Can we dynamically show/hide the columns of a List Datagrid based on the filters values?
I do not see how we can do this. Thanks for any help on this.
This is not possible with the default ra-ui-materialui List component. You'll have to implement your own, using it as a starting point.
Feel free to open a feature request issue on the https://github.com/marmelab/react-admin repository describing the use case.
You can refer to this link for customizing your datagrid columns : https://github.com/fizix-io/ra-customizable-datagrid
OR,
you can make your list component as a stateful component, and implement your own Actions in the List component like a toggle button.
For Example:
class MoreDetails extends Component {
constructor() {
super();
this.state = {
showDetails: false
};
}
toggleDetails = () => {
const toggle = this.state.showDetails;
this.setState((prevState, props) => {
return {
showDetails: !toggle,
}
});
}
render() {
const { classes, ...props } = this.props;
const MyActions = ({ basePath, data, resource }) => (
<CardActions style={cardActionStyle}>
<Button
color="primary"
onClick={this.toggleDetails}
>Toggle Details</Button>
</CardActions>
);
return <List
actions={<MyActions />}
{...props} >
<Datagrid>
<TextField source="c1" label="Column1" />
<TextField source="c2" label="Column2" />
{this.state.showDetails ?
<TextField source="c3" label="Column3" /> : null }
<TextField source="c4" label="Column4" />
{this.state.showDetails ?
<TextField source="c5" label="Column5" /> : null }
</Datagrid>
</List>
}
}

Can't render image from state in React/JSX

I'm getting the path to an image from my database. The image file is stored locally. I store the path as State for the component thus keeping the component dynamic as opposed to simply importing the path form it's location. So...
this works...
render() {
return (
<div>
<Col xs={6} md={4}>
<Image src={require('../../../../public/uploads/file-1516414373384.png')}responsive />
</Col>
</div>
)
However, this does not...
class Reports extends Component {
constructor(props) {
super(props);
this.state = {
reports: [],
photos: null
}
}
componentWillMount() {
var reports = []
axios.get('/uploadUserImage')
.then( (response) => {
response.data.forEach(function(report){
reports.push(report)
})
}).then(() => {
this.setState({reports})
}).then(() => {
var path = '../../../../'+this.state.reports[0].file;
var rightPath = path.replace(/\\/g,"/");
this.setState({photos: rightPath})
})
.catch( (error) => {
console.log(error);
});
}
render() {
return (
<div>
<Col xs={6} md={4}>
<Image src={require(this.state.photos)}responsive />
</Col>
</div>
)
Even though the second non-working code compiles to the same this as the first working bit of code.
I get an error that says
Uncaught Error: Cannot find module "."
So maybe there is something wrong in my web-pack? but if that were true wouldn't both cases throw the error???
I also tried template literals...
<Image src={require(`${this.state.photos}`)}responsive />
As was the answer to a similar question, but no dice - Same error.
I think, this is because first time it trying to import image of path null (initial value of the path in state), only after getting successful response from server, it will have the correct image path.
One possible solution is, render the image only when you have a valid path means after getting response, Use conditional rendering and put the check.
Like this:
{this.state.photos ? <Image src={require(this.state.photos)} responsive /> : null}
It’s OP. I tried everything suggested here and in other similar questions. Nothing worked. I installed react-image and now everything works fine.
Wish I could give an explanation as to what’s going on under the hood, and what exactly went wrong before, but I don’t really know. Images do render now via component state. So, victory I guess.
I was running into a similar issue and found this to work in my project:
import React, { Component } from 'react';
class ImageUpload extends Component {
constructor(props) {
super(props);
this.state = {
file: null
};
this.handleChange = this.handleChange.bind(this);
}
handleChange = e => {
this.setState({
file: URL.createObjectURL(e.target.files[0])
});
};
render() {
const fileAttached = this.state.file;
return (
<div>
<input type="file" onChange={this.handleChange} />
{fileAttached ? (
<img
src={this.state.file}
alt="File Uploaded"
height="300"
width="400"
/>
) : (
<img src="" alt="No file uploaded" />
)}
</div>
);
}
}
export default ImageUpload;

Redux-Form Field-Level Validation: Why aren't the error messages showing?

In using redux-form with React, I'm having an issue where the error messages are not displaying for field-level input validation.
Here is the relevant code from the component:
const renderField = ({input, placeholder, type, meta: {touched, error, warning}}) => (
<div>
<input {...input} placeholder={placeholder} type={type} />
{touched &&
((error && <span>{error}</span>) ||
(warning && <span>{warning}</span>)
)
}
</div>
)
const required = value => {
console.log("required");
return value ? undefined : 'Required';
};
const Question = props => {
const { handleSubmit, onBlur, question, handleClick } = props;
return (
<div className={`question question-${question.name}`}>
<form className={props.className} onSubmit={handleSubmit}>
<div className='question-wrapper'>
<label className={`single-question-label question-label-${question.name}`}>{question.text}</label>
<Field
component={renderField}
type={question.type}
name={question.name}
placeholder={question.placeholder}
onBlur={onBlur}
validate={required}
/>
</div>
</form>
</div>
)
}
export default reduxForm({
form: 'quiz',
destroyOnUnmount: false,
forceUnregisterOnUnmount: true,
})(Question);
When I test it, I see that in the console the UPDATE_SYNC_ERRORS action is being called, and the console.log("required"); is also showing up. But when I navigate to the next question, neither on the screen do I see the error message, nor do I see any evidence of it when I inspect the component with DevTools.
I've been following the example on Field-Level Validation shown in the redux-form docs here: http://redux-form.com/6.7.0/examples/fieldLevelValidation/
Any idea what could be causing this? Thanks in advance!
Well, you have to write a validate function, and pass it to the reduxForm helper or wrapper like this. Redux-form will pass all the form values to this function before the form is submitted.
function validate(values) {
const errors = {};
// Validate the inputs from 'values'
if (!values.name) {
errors.name = "Enter a name!";
}
...
return errors;
}
export default reduxForm({
validate,
form: 'QuestionForm'
})(
connect(null, { someAction })(Question)
);
Hope this helps. Happy Coding !
you can also provide validate like this
const formOptions = {
form: 'yourformname',
validate: validatefunctionname,redux-form
};

In list component, how to implement a component to change the number of results displayed

I was thinking about making a simple component with a Select and the list of results that should be displayed.
After reading the code, that seems impossible, because if I change the url, then update is triggered by componentWillReceiveProps, and this method does not check for a change of perPage
Change the prop perPage of the List component does not work either because the List use this prop only if the query does not already contains perPage
Here is an example of what I want to do :
import { List } from "admin-on-rest";
class SourceList extends Component {
constructor(props) {
super(props);
this.state = {
perPage: 10
};
}
render() {
return (
<div>
<Button
onClick={() => {
this.setState({ perPage: 50 });
}}
/>
<List {...props} perPage={this.state.perPage}>
... Here would be the content of the list
</List>
</div>
);
}
}

How to render a container dynamically in react-redux?

I am new to redux-react so excuse me if it is a stupid question.
I have a page which shows the list of some products in a table.
When I click on a product, I want to show details about that product in a panel overlaying the main page.
The problem is that the detail page has already a component and container class.
If I want to render the component I have to mix the main page and detail page containers together which I don't want. I want to keep each page component and container separate.
When I render container I get the error
Invariant Violation: Could not find "store" in either the context or props. Either wrap the root component in a , or explicitly pass "store" as a prop.
I don't know how to pass it and I googled about it I couldn't find a solution for my case. I don't want to initialize a new store.
Here is my click function to show the detail page.
onClick(){
ReactDOM.render(
<div>
<div className="my-panel" id="my-panel" data-toggler=".is-active">
<ProductDetailContainer />
<button className="button" data-toggle="my-panel">Close</button>
</div>
</div>,
wrapper
);
}
here is my product detail container code:
export class ProductDetailContainer extends RootContainer {
constructor(props) {
super(props);
this.state = {
productDetail: {}
};
}
componentDidMount() {
this.props.dispatch(someAction);
}
componentWillReceiveProps(nextProps) {
//some code here
}
handleRefresh() {
//some code here
}
render() {
return (
<div className="row small-12 columns">
<ProductDetailComponent
data={this.state.productDetail}
/>
</div>
);
}
}
ProductDetailContainer.propTypes = {
productDetail: PropTypes.object
};
export function mapStateToProps(state) {
return {
productDetail: state.productdetail
};
}
export default connect(mapStateToProps)(ProductDetailContainer);

Resources