Generate Madlib and Clear Form Buttons in React
Welcome back to the course. In this guide, we're going to learn how to show and hide this component, so that when we hit the generate button we can show and hide.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

First, what we're going to do is add in the button, and then we're going to show and hide it. Let's head over to our application. Let's close the terminal, and close the input.js. Let's go to our card.js. What we need to do is provide a button, and let's see where we want to put that. What I want to do is wrap all of our inputs in a div, and then put a button after that.

So I'm going to put:

card.js

        return(
            <div className="card">
                <div className="card__inputs">
                {
                    inputData.map(data => Input( (data), this.handleInputChange )
                }
                </div>
                <button>Generate Mad Lib</button>
                <Content data={this.state}/>
            </div>
        )

I'm going to open my terminal go to the node and I'm going to close my server. OK. So basically I just switched over to my other terminal instance and I stopped my server, and I'm going to start it back up. That's very aside from what we're doing. All that I did that for is so I could change it to a better day.

Now we have this button and card__inputs inputs div. You'll see in here that we have this button, but it doesn't actually do anything. That's pretty exciting, to say the least. What we need to do is provide a function in this button, but we can't because it's a form button.

What we need to do is make this div a form. We need to say:

card.js

        return(
            <form onSubmit={this.handleInputChange} className="card">
                <div className="card__inputs">
                {
                    inputData.map(data => Input( (data), this.handleInputChange )
                }
                </div>
                <button>Generate Mad Lib</button>
                <Content data={this.state}/>
            </form>
        )

Obviously, we don't want to run this function. I was just typing that out to show you that it's a function that we need to put in there. So right below handleInputChange, I want to put:

card.js

handleFormSubmit() {
    console.log('trying to handle form submit');
}

Let's save that. Let's go down here, and it's not going to work. It's going to reload our page, and it's going to provide us with all of our data up here, but it's not going to work. We're not actually going to worry about this data. We are actually going to pass it through a different way. This would be relevant if we were using something like redux-form, or if we were browsing our data to an endpoint.

large

The reason that happened actually is because we never changed it. It's still handleInputChange, so let's get handleFormSubmit and let's replace it in our onSubmit.

card.js

        return(
            <form onSubmit={this.handleFormSubmit} className="card">

So that's handleFormSubmit. Now when we reload the page it's still not going to work, but you'll see it for a brief second. It says: trying to handle form submit.

large

What we need to do is we need to go here and we need to say:

card.js

handleFormSubmit(event) {
    console.log('trying to handle form submit');
    event.preventDefault()
}

Basically, this is just giving us our form. Now when we hit it: it doesn't reload the page. It doesn't do the default action. We're still getting the trying to handle form submit. What we need to do is get rid of this console.log, we need to say on this button:

card.js

                <button type="submit">Generate Mad Lib</button>

That's not going to change anything in the application at all, but it's how you should declare your button if you want it to be a form submit. That's what we're doing so it can have the same action. Now we need to figure out how we can render this content when we click this.

large

We initially don't want it to be rendered, so we can do this using a piece of state called whatever we want. We can put it in its own object, or we can just copy it and put it right here. Let's make an object. We could say: "Let's call this contentVisible and set it to a default of false."

large

Now, all we need to do is only display it if this is true. So let's good down here, and let's say:

card.js

        return(
            <form onSubmit={this.handleInputChange} className="card">
                <div className="card__inputs">
                {
                    inputData.map(data => Input( (data), this.handleInputChange )
                }
                </div>
                <button>Generate Mad Lib</button>
                {
                    this.state.contentVisible ? <Content data={this.state}/> : <div>hello</div>
                }
            </form>
        )

This is a ternary expression in JavaScript. It's in many other languages too. Basically, what this is doing is saying: if the content is to visible then we're going to return this data. If it's not visible or else let's return this content. With this being false, as you can imagine, it's going to render 'Hello'. You'll see that it says hello now.

large

Now we just need a way to say that we want this to change to true and generate. We already know how to do that by using this.setState. All that we have to do say:

card.js

handleFormSubmit(event) {
    event.preventDefault()
    this.setState({ contentVisible: true })
}

Now, this is going to show our content now, except for it's not going to work because we haven't bound our function. So what we need to do is what we did with handleInputChange in the constructor. We need to copy this and say:

card.js

this.handleInputChange = this.handleInputChange.bind(this);
this.handleFormSubmit = this.handleFormSubmit.bind(this);
``

Now when we generate you'll see it shows, but how do we get back? How do we clear the Mad Lib? That's pretty simple. All we need to do is render a different button and set the state back to false. 

![large](https://s3-us-west-2.amazonaws.com/images-devcamp/Comprehensive+React+Development/React+Project+One%3A+Build+a+Madlib+Game/Generate+Madlib+and+Clear+Form+Buttons+in+React+%23+1899/Image16.png)

We can set the state back to false by instead of hard coding it in as true or false. We can just say:

**card.js**

```javascript
handleFormSubmit(event) {
    event.preventDefault()
    this.setState({ contentVisible: !this.state.content })
}

So what this is doing is swapping it. Right now, if we were just to do this.contentVisible, it's just going to set it to what it is. So it's just going to set it to false over and over again. By saying ! or not, it's going to get the opposite value.

By providing the exclamation point, it's going to switch this to true and set it and then this is going to be true. Then when we submit again, it's going to swap it to false. If we generate, it will go back and forth.

It's awesome, but we want this to display different text, and there's a number of ways we can do that. One of them is by saying: if content is visible I want to return another button. I'm going to do the same thing with this except a return button, or we could just do it on the text. We could say:

card.js

                <button type="submit">{this.state.contentVisible ? 'Generate Mad Lib' : 'Clear Form'}</button>

This is just going to return one of these based on the value of contentVisible. You'll see that it says: Clear Form. It's assuming there are values in here. These are set backward, so what we can do is we can either switch these or we can say not or ! in front of this.state.contentVisible.

card.js

                <button type="submit">{!this.state.contentVisible ? 'Generate Mad Lib' : 'Clear Form'}</button>

It's going to switch the values. You get the idea. Hopefully, if you don't: just kind of think about that for a second. We're typing in the values, and then we can type in Generate Mad Lib, and it generates it. Then we can hit clear form and it'll go back to generate, and it will be gone.

Our inputs are still here. We want to clear the data from these inputs, and that would be good. What we should do is end the guide here because it's going on, but we've got the button in there and it's rendering and un-rendering the content.

large

Let's go ahead and get rid of this Hello. Let's go here and just get rid of this and just put:

card.js

                {
                    this.state.contentVisible ? <Content data={this.state}/> : ''
                }

Now it's going to render nothing. So we go in here, hit generate, clear, generate, clear. You can see what's going on. So let's commit our code, and then in the next guide, we will learn how we can clear the form when we hit the clear button. Right now all it's doing is hiding this. We want it to clear all these values.

Let's say in the terminal: git status, git add ., and let's say git commit -m "added content visible state and generate and clear buttons with functionality". I'll see you in the next video where we will learn how we can actually clear this data when we hit clear form, and not just hide the data. Let's go ahead and end the video.

Resources