Since every time we interact with one of the dropdowns the information is shared between the 4 of them, the time as now arrives to give each individual dropdown its own state. We will also add subscriptions to listen to when the user clicks outside each dropdown!
To do this, we'll need to extend our state model to include each instance of our viewCard
. To determine which dropdown that was clicked we will create a getDropdownState
function that pattern matches the correct card instance. During this process, you'll see how the Elm compiler guides us through adding this functionality with detailed error messages.
You'll see how adding a subscription to close open dropdowns is convenient as Dropdown
gives us an onOutsideClick
function that receives the model and dropdown message.
Flavio Corpa: [0:00] Now the time has finally arrived for each separate dropdown to have its own state. How can we do that? First things first, we need to create four different dropdown states. We're going to copy this and say overall dropdown state. Now category1, dropdownState : Dropdown.State String, and the same three times. Pretty boring.
[0:23] Now we need to initialize these three times, Dropdown.init. We're going to call it category1. This one, we're going to call it overall. This one, is going to be category2, category3, category2 and category3. Nice. Let's check the compiler.
[0:39] In our model, when we update, we don't know exactly which dropdown to modify. Then we go down. When we view the dropdown, we have exactly the same problem. We should choose which dropdownState we need to represent.
[0:53] In order to do that, we're going to create a new function her called getDropdownState. It's going to take a Model, a menu, and the dropdownState, and it's going to return the Dropdown.State String.
[1:07] This is going to be the Model menu, case menu off. One thing that would be nice is to define what is going to be our menu. For defining our menus, we're going to create a new custom type called menu that is going to be overall or category1, or category2, or finally, category3, perfect.
[1:30] Back to our function, if the menu is overall, we're going to return the model.overallDropdownState. If the menu we're selecting is category1, we're going to return the state for category1, and the same with the other two. Nice, this is now correctly formatted. When we go here, now we need to say getDropdownState(model, menu), but we don't have the menu.
[1:55] In our update function, where are we going to get our menu from? We're going to pass here the menu. We need to reflect that change in our type, menu. Let's fix the errors one by one. Here, we need to patch for match menu of if overall, we're going to return the state change for overallDropdownState and we're going to repeat the same for the other cases.
[2:17] In our dropdown message, we need to pass the menu in which we are, our message. As you see this is our dropdown config. Dropdown config needs to take as an argument the menu to which it belongs. If we scroll to the bottom and we display a dropdown, we also need to know which dropdown now we are calling.
[2:40] GetDropdownState(model, menu). This belongs to the card function, so now our card function also needs to take the menu to which it belongs.
[2:50] Now it's time to go to our cards and tell to each individual card that this card is going to be the overall menu, this card is going to be the category1, category2, and finally category3. This needs to go as a second argument.
[3:06] We need to also pass the menu parameter to our dropdown config function, and finally, in our view again we need it here. As you see, the compiler, very nicely and politely tells us what code needs to be modified...We're good to go now, and as you see, if I click something here, this dropdown has its own state, this one has its own state, and all of them have their own state. Gorgeous.
[3:28] You might have noticed that none of them are closing whenever we click outside, or we click another dropdown, which is quite annoying, to be honest. That's why we need now to create a subscription in which we're going to say subscription batch because we're going to listen to many.
[3:44] What's very nice about this library is that dropdown comes with a very handy onOutsideClick function that receives the model to which we want to listen to, and the dropdown message, and of course here we also need the dropdown again for which we need to listen to.
[3:58] We're going to do this three times more. Now we go back to our main function, and we replace this via actual subscriptions, and now if we click outside, all of them should close. Beautiful. What you see now, all of them are closing, and it works perfectly.