2.2 Using Custom Events and Applying State
We need a visual cue to let users know which feed they selected. We will implement that functionality with the help of the
EventTarget interface and custom events.
1.Introduction2 lessons, 06:43
1.2Setup and App Walkthrough05:20
2.2Using Custom Events and Applying State09:22
2.3Code Reuse, Not Code Duplication13:26
2.4Displaying the Article Content02:55
3.Conclusion1 lesson, 01:10
2.2 Using Custom Events and Applying State
We got a pretty good start in the previous lesson. We fetched our feeds, and we are displaying them in the UI. And of course, we have classes that are making all of that work. But we have a little problem. Whenever we click on one of these feed objects, nothing happens. Now, let me talk about terminology. I'm going to refer to these as feed objects. Yes, I know that they are A elements but logically, behind the scenes, these are feed objects. So whenever we click on the feed object, nothing happens. Well, part of that is by design because you wrote the code to do that. We are preventing the default action from occurring whenever we click on them. But we do want a visual cue so that whenever the user clicks on one of the feeds, that they know that I clicked on this, this one's active. So I do have a CSS class that we can use to facilitate that. So whenever we click on one of these objects, we can simply add the active class to the class list. And there we have our visual cue. But whenever we click on any other feed object, well that one's going to be active to and nothing deactivates. Well, we can't really rely upon the feed class for that functionality because each feed object is only aware of itself. It doesn't know of any other feed object. However, we do have a container class. That is aware of all the feed objects. So we could bring that in to help maintain the act of state of all of our items. And if you remember from the previous lesson I said that, there is going to be some overlap in responsibility and functionality between our container class and then the feed objects, and this is one of those cases. Now, the API for changing the state of each individual feed is going to be inside of the feed class. But we are going to use that API inside of the container class, just like we called the render method here, we're going to work with a property called active. So one thing that we can do is piggyback off of the click event for our HTML object. Because what we can do then is extend the EventTarget interface. This is the interface that is used for all of the dom objects that support events. So by extending EventTarget, all of our feed objects have the add event listener method. So what we could do is this, whenever we create our feed object, we could go ahead and add an event listener for an event called active or activate. And we could have a call back that will then, let's do this, let's call a method called this.setActiveItem. One thing that I need to remember is that, for right now, this item container is rather generic. So something that we will need to do is rename this loadFeeds to like loadItems or something. But we will get there, especially whenever we start working with our articles. So we're going to say, setActiveItem. And then we can pass in the target of the event that's going to be the feed object that we work with. So that inside setActiveItem, all we will need to do then is iterate over our items, so let's go ahead and do that. We can use the forEach method. And forEach thing inside of our items, we can check for the active state. Well, this is what we'll do, we'll say thing.active. So for our feed object, we're going to add an active property and we're going to set that depending upon if thing is equal to item. If it is, then of course, that's going to be true. Well, we don't even have to do that. That's all that we need there. So, let's write this active property and then we will fire that event. So, let's make this a setter and we might add a getter for this, but for now, all we need is a setter. So I want to stick with a code that we currently need. So we're going to set active, we're going to get a value and we're going to do this. We're going to say let method =, and if value is true, then we're going to add our active class. If not, we're going to remove the active class, so that we can say this.el.classList, then we'll specify our method, and then active. And that should work so that now, all we need to do is actually fire that event. We'll sense this extends EventTarget, what we can do is create an event and we do that with the CustomEvent constructor, we specify the name of the event that we want to occur. And then we will dispatch that event and we do that with a method called dispatchEvent, that is of course given to us by the EventTarget. So that's now well, nothing works, we broke something. So if we look at the error, must call super constructor in derived class, duh. So let's call super inside of the constructor for feed. Now, that works and whenever we click on one of these, we see that it is now active. If we click on the other feed object, we see that the Tuts+ Twitter Feed becomes deactive and the PRS Guitars is active. And we can just keep going back and forth, back and forth, back and forth, and that's perfectly fine. Now, whenever we click on a feed object, we want to load that feed so that we can then load the articles list. So we can do that essentially the same way that we signified that a feed object is active, and that is using the CustomEvent. But this time, we're going to do it on our ItemContainer so that it extends EventTarget. Let's not forget to call super in the constructor so that we won't get that error again. And we would want to do this when the ActiveItem changes. So we will just call it that. So let's create an event, new CustomEvent, we will call it selectedItemChanged. And we can also specify some detail information, because in this case, it makes sense that we want to tell whatever's listening for this event, what that new item is. And we can do that by passing an object as the second argument that has a detail property, and then that detail can be whatever it is that we want it to be. It could be another object that has several properties, but in this case, we just want to signify that the detail is the item that changed. So we could just say that, hello, it's the item. And that would be fine so that then we would dispatch the event, and then the application object would be listening for that. So we could set this up inside of init, so that we will say this.feeds.adEventListener ('selectedItemChanged', and then we would have our call back. But in this case, let's break this out into another method, so that we will call like loadFeed or something like that. And then we would pass in the item that is now active. And that will allow us to then retrieve that feed and then load the articles in the article list. So we will just define loadFeed, we will accept that feed object and then let's add a to do. Get feed, load articles. Now the last thing I want to do is go ahead and change the name of this loadFeeds. It's not loadFeeds, it should be loadItems, so let's change that. We, of course, need to change where we call that, which is right there. And some of the names here can change as well, but really, there is stuff that is specific for feeds and so, we're going to leave that until we need to subclass and things like that. So for right now, we have much more going for us. In the next lesson, we are going to write the code that is going to load the feed and populate the article list.