- Read Tutorial
- Watch Guide Video
So what I want to do is throw in these pieces of data into our fields in newsletterNewForm.js
newsletterNewForm.js
import React, { Component } from "react"; import { reduxForm, Field } from "redux-form"; import { FormTitle } from "../formTitle"; import { FormInput, FormButton, FormTextArea, FormImage } from "../formFields"; class NewNewsletterForm extends Component { render() { const { handleSubmit, formTitle, newsletterToEdit } = this.props; const { title, body, imageUrl } = newsletterToEdit; return ( <form onSubmit={handleSubmit} className="new-newsletter-form"> <FormTitle className="new-newsletter-form__title" text={formTitle} /> <Field className="new-newsletter-form__newsletter-title" placeholder="Newsletter Title" name="title" type="text" title="Newsletter Title" component={FormInput} value={title} /> <Field className="new-newsletter-form__body" placeholder="Newsletter Body" name="body" type="text" title="Body" component={FormTextArea} value={body} /> <Field className="new-newsletter-form__submit" small={true} danger={true} name="submit" type="submit" title="Submit" component={FormButton} /> <Field className="new-newsletter-form__cancel" small={true} name="cancel" type="button" title="Cancel" component={FormButton} onClick={this.props.onCancel} /> <Field className="new-newsletter-form__image" small={true} name="image" type="file" title="Image" component={FormImage} src={imageUrl} /> </form> ); } } NewNewsletterForm = reduxForm({ form: "newnewsletter" })(NewNewsletterForm); export default NewNewsletterForm;
Let's hop into formFields.js
and add in our values. We're going to set up a ternary expression, because this data won't always be here, like when we create a new newsletter. We'll start with title.
formFields.js
export class FormInput extends Component { render() { const { className, title, input, type, placeholder, value } = this.props; return ( <div className={`${className} form-input`}> <label className='form-input__title'>{title}</label> <input className='form-input__input' type={type} {...input} placeholder={placeholder} value={value ? value : ''} /> </div> ) } }
Basically it's asking if the title exists as value, and if it does it will render that data, otherwise, it will just put an empty string. Let's go to the text area and do the same thing.
formFields.js
export class FormTextArea extends Component { render() { const { className, title, input, type, placeholder } = this.props; return ( <div className={`${className} form-textarea`}> <label className='form-textarea__title'>{title}</label> <textarea className='form-textarea__input' type={type} {...input} placeholder={placeholder} value={value ? value : ''} > </textarea> </div> ) } }
Image is ok by itself since it's already set up. Now, if we were to go to the browser to try this out, we would encounter an error that won't let us log in. This is happening because we directly messed with our form for inputs by telling it to throw in an empty string if no data is present. We need to set this up so that it won't affect the rest of our inputs.
We could build a separate form input just for our edit, but we don't need to do that, neither do we need to build a whole separate component just for this. What we need to do is just say if it doesn't exist then we don't return an empty string. We want to return a value, so we'll say input.value
and see if that works.
formFields.js
export class FormInput extends Component { render() { const { className, title, input, type, placeholder, value } = this.props; return ( <div className={`${className} form-input`}> <label className='form-input__title'>{title}</label> <input className='form-input__input' type={type} {...input} placeholder={placeholder} value={value ? value : input.value} /> </div> ) } }
And it works. So the reason that works is that we already have an input. Now inside of our form input, we already have a ...input
So we might be able to put that below and it would work, even if we change it back to an empty string since input has a value, so it will override it.
Now this might be a problem when we get to our newsletter edit because we going to put value in and then it'll override it with a blank value. So let's go try that. Click on edit and you'll see it's value is not defined even though we checked it.
So it's saying value is not defined for some reason. Let's check where that's occurring. In our error message, it says that it's occuring in formFields.js
on line 34, which means that it's down here in form text area. And that's because we didn't pass in value, so let's do that.
formFields.js
export class FormTextArea extends Component { render() { const { className, title, input, type, placeholder, value } = this.props; return ( <div className={`${className} form-textarea`}> <label className='form-textarea__title'>{title}</label> <textarea className='form-textarea__input' type={type} {...input} placeholder={placeholder} value={value ? value : ''} > </textarea> </div> ) } }
And now it should work. Let's check our edit page. Nope, still not working. We are getting our values through redux, but it's not going into our forms. So let's go to newsletterNewForm.js
and we're providing it as a prop which means we're probably trying to override something that already exists. What's really happening is we're trying to overwrite a prop that is already called value.
So let's just call these editValue and see what happens. We have to change this in formFields.js
and newsletterNewForm.js
.
formFields.js
export class FormInput extends Component { render() { const { className, title, input, type, placeholder, editValue } = this.props; return ( <div className={`${className} form-input`}> <label className='form-input__title'>{title}</label> <input className='form-input__input' type={type} {...input} placeholder={placeholder} value={editValue ? editValue : input.value} /> </div> ) } } export class FormTextArea extends Component { render() { const { className, title, input, type, placeholder, editValue } = this.props; return ( <div className={`${className} form-textarea`}> <label className='form-textarea__title'>{title}</label> <textarea className='form-textarea__input' type={type} {...input} placeholder={placeholder} value={editValue ? editValue : ''} > </textarea> </div> ) } }
newsletterNewForm.js
<Field className="new-newsletter-form__newsletter-title" placeholder="Newsletter Title" name="title" type="text" title="Newsletter Title" component={FormInput} editValue={title} /> <Field className="new-newsletter-form__body" placeholder="Newsletter Body" name="body" type="text" title="Body" component={FormTextArea} editValue={body} />
Let's check that out in the browser.
As you can see it works, so that's great. So that was obviously what was going on. It was trying to see value but likely in redux there is a property called value that was overriding whatever we are putting in value. We can log in, view the newsletter, and then go into edit.
It may have broken our new newsletter component, though. You see we have an error saying that title is undefined.
So in our newsletter new form it's saying title is undefined in our newsletterNewForm.js
. So basically what's happening is it's trying to get our data and throw them in, but they don't even exist, so we can quickly fix this by just doing exactly what we did in our formFields.js
and putting these ternary expressions in.
newsletterNewForm.js
<Field className="new-newsletter-form__newsletter-title" placeholder="Newsletter Title" name="title" type="text" title="Newsletter Title" component={FormInput} editValue={title ? title : null} /> <Field className="new-newsletter-form__body" placeholder="Newsletter Body" name="body" type="text" title="Body" component={FormTextArea} editValue={body ? body : null} />
Now let's try it out to make sure it is working. And we get an error. So we need to do is set it up so that it will only pass in those values if newsletterToEdit exists. so we need to put this in a conditional up above. We'll have to create new variables because our scope will be changed.
newsletterNewForm.js
render() { const { handleSubmit, formTitle, newsletterToEdit } = this.props; var title = null; var body = null; var imageUrl = null; if(newsletterToEdit) { title = newsletterToEdit.title; body = newsletterToEdit.body; imageUrl = newsletterToEdit.imageUrl; }
Okay so pretty simple. It's just going to check if they exist. So let's save that let's go check it out now. Should be working.
And it works. Our edit form has all of our text in it, while the new form is empty. But we also need to show the image when we edit because you'll see it's not showing the image. So what we need to do is go to our form image and see what's going on.
It looks like we'll need to change the form input to say imageUrl
, instead of src.
newsletterNewForm.js
<Field className="new-newsletter-form__image" small={true} name="image" type="file" title="Image" component={FormImage} imageUrl={imageUrl} />
So yeah that's how you edit it. Let's go ahead and get rid of some of the console.logs
. You definitely just don't want console logs randomly in your application. You also don't want them in production especially if you're printing out data, because you don't want to just print out random data because that's a bad experience and it could be user data that you don't want vulnerable.
Let's commit our code and move on.
git status git add . git commit -m "mapped newsletter edit data into form"
I'll see in the next video.