In this lesson we are going to learn how to use inputs and outputs to create smart and dumb components. In Angular 2 components communicate via the concept of inputs and outputs which is very similar to isolated scope in Angular 1, property data go in and user events come out.
This allows us to create components that are dumb in the sense that they contain no logic whatsoever, and their only function is to display data and relay user events back to its parent component. This reduces our testable surface area significantly, because unless Angular has broken, there is really nothing to test. We can then use smart components to coordinate the layout of our dumb components, and then we pass user events back to the appropriate services.
We're going to start by building out a categories item component. I've went ahead and put in the styles and the category item module, and so we're going to get started at the category item component. So the first thing we're going to do is import our template, and the we'll go ahead and import our styles, and then we will define our component configuration object. Before I forget, I'm going to export this, then I'll do the template controller as, now the interesting thing about components is that if you do not explicitly define a controller it will just implicitly create one for you.
Now in Angular 1 we would define isolated scope by creating a scope object and then saying that we want to pass in a category and set that to two-way databinding. It then turned into bindTo, and it's now bindings. This would work, but we're going to change it to one-way databinding using this > symbol, so it binds from the parent to the child and change detection is only on the parent, not on the child. Now let's update our template, and then we're going to just bind to categoryzitemController, category, this is what we're passing in, and then the main property on that object.
Now let's go ahead and add in the categoryItem module to our categories module so that we have connected the dots, and then we'll go ahead and add this as a dependency. From here, we need to update the categories.html to use our categoryItem component. So we'll delete this class first, then we'll delete this, and then we'll go categoryItem, and then we're going to define a category attribute and pass in our category object.
Let's hop into the browser, and you can see that it's working, but just to prove that it is, let's go ahead and update this template and we'll just put two exclamation points in here. We'll hop back into the browser, and so you can see that we're rendering the categoryItem component. Now that we've created an input, let's go ahead and create an output. Let's hop back into our categoryItem component, and we want to create an output of selected, so that when an item is selected, then it emits an event that we can bind to.
That's just expression isolated scope. We'll capture the ngClick event, and then from here we're going to call categoryItemControl.selected because that is what we defined on our bindings object. Now this has to be in object map, we send parameters back. This is the one gotcha that gets me. We're sending in a category object and then we're passing a categoryItemController. Then within or categories.html, let's update this to capture the selected event, and then we're going to call an onCategorySelected method on our categories controller.
We'll just pass in the category. We'll go ahead and scope this to the categoriesList controller. Then we need to um into our categoriesList controller and then define that. We'll go to categoriesList controller, and we'll define this method on categorySelected, and we'll pass in the category. Then from here we're just going to log this output to the command line. So we'll go categorySelected and then we'll just dump the category object that we're passing in. Let's hop into the browser and see this working.
We click a category item, you can see that it has been logged to the console. Let's just do a quick review. We created our category item component that has a category input and a selected output. From there, we are binding to the category input and then onClick we're calling categoryItem controller selected, and passing in the category via an object map, as that is our output.
Then in our HTML we're passing in category, and the we're binding to the selected output which then in our categoriesItemController, we're capturing the selected event and then deferring that to onCategorySelected which we are logging to the console. Now one thing I want to point out is that you'll notice in the CategoryItems component there is no controller, it's completely dumb. This is how you create smart and dumb components in Angular 1 and in Angular 2 style.