Building CampaignHawk: Trigger Functions with Radio Buttons (Part 15)

Now that we have our popout with radio buttons that will eventually control data layers, we want those buttons to trigger different functions. Each of those functions will generate a new data layer that will be overlaid on our map.

For now, we’re just going to get our radio buttons to trigger different functions. You’ll recall that our data layers are handled within our MapChild component, so we want our radio button event functions to be handled there and passed down through our Sidenav component.

In our MapChild component, let’s create a toggleDataLayer function that we will use to toggle our data layers based on the status of our radio buttons. In this function, we’re taking in the name of the layer from the id of the selected radio button (as you will see later), checking to make sure our data is loaded, then logging the layer name.

Also, if the data is not loaded, we will get an alert and the layer will try again 3 seconds later by recursively calling itself. Our data should load very quickly, so this will almost never happen. We probably want a spinner here rather than an alert, but this will do for now.

toggleDataLayer(layerName) {
if (!this.props.loading) {
console.log(layerName);
} else {
alert("Not ready. Retrying in 3 seconds.");
setTimeout(() => {
this.toggleDataLayer(layerName);
}, 3000)
}
},

Now we need to pass this toggleDataLayer function down to our Sidenav, then into our SidenavIcons, then to DataLayerPopoutContent.

<DataLayerPopoutContent 
toggleDataLayer={this.props.toggleDataLayer} />

Within our DataLayerPopoutContent component, we want to create another function that handles any changes on our radio button group. We can do this by creating another function; we will call ours handleDataLayerChange.

handleDataLayerChange(e) {
this.props.toggleDataLayer(e.target.id)
},

In this function, we are calling toggleDataLayer and passing in the id of the radio button that is now selected. Using this, we can trigger the appropriate data layer function. In each of our inputs, we need to add an onChange event handler that calls handleDataLayerChange:

onChange={this.handleDataLayerChange}

And now, when the various radio buttons are clicked, the id of that button is logged to the console.

One last thing we probably want to do before moving on to Mapbox is give ourselves the ability to close our popout. To do this, we have to change the name of our state variables to showPopoutState to distinguish it from the showPopout function wherever necessary. We might as well do this for the tooltip as well.

I’m not going to write out the code for all of this because it would be tedious, but there is one thing worth noting. We need to change our case for “Data Layers” to call a function outside our switch. Let’s create that function and call it handlePopoutClick:

handlePopoutClick(data, e) {
this.props.showPopoutState ?
this.props.hidePopout() :
this.props.showPopout.bind(null, data, e)();
},

The reason we need to break this out of our switch statement is that we need access to the value in this.props.showPopoutState, which changes after we call show or hide. If we leave it in the case statement, the value will always be set to false because that was the value of showPopoutState when the click event listener was created.

So now we need to change our case to call our click handler:

case "Data Layers": return this.handlePopoutClick.bind(null, <DataLayerPopoutContent />);

Also, back to making sure our tooltip doesn’t trigger when we have an active popout, there is an easier way than removing the event listener: we can set a conditional within our showTooltip function. All we have to do is add the following conditional:

showTooltip(e) {
if (this.state.showPopoutState) { return null; }

Next Steps

The app is now pretty well structured. The next few steps revolve around properly structuring our data and working with the Mapbox API. Unlike the last several articles, I have a feeling that these next steps will take significantly longer to code than to write into articles.