In collaboration with CodeSchool, John refactors pieces of the CodeSchool Angular app into a more reusable directives.
Man 1: The Code School Shaping Up course ended by extracting HTML into a bunch of different directives. One of the examples is this product description directive, which you can see here, which is an element that loads this product description template.
Where they left it this product description directive is not very flexible or reusable, because this product object right here is bound all the way back to the product from this repeater in the index file. It's declared here, it goes down into the product tabs which is here, and then back down into the product description where it's shown here. This product is this product from the repeater.
You can see that this directive is tightly coupled to this container because it relies on this being named product, or else this will break. The way we can fix this is by using the scope. We'll declare a scope, and inside that scope we'll say that an item is the two-way binding, so whatever object we pass in is bound on both sides. If you've seen other things on directives you know there's other options, but this is the main use case so we're just going to focus on this for now.
This means that if I take item, and wherever I declare this product description I can say item, and then I can pass in the product. That means that I can say this isn't the product, it's whatever gets passed in. You can see if I refresh here, this still works just fine. What this allows us to do is to use this product description directive in other places. Say for example I want to use it outside of that repeater, I can use a product description and then give it an item. We'll just pass in an object with a description, because that's the only requirement. We'll say the description is wow.
If I refresh here, you can see I have used my description directive outside of this repeater, so it doesn't rely on this product to be defined. I can use this product description directive wherever I want to.
Let's do a similar refactoring to the other directives inside of product tabs. Let's look at product specs. We'll navigate straight to that. We'll give it a scope, just like we did before, and our scope will have an item. Then where we declare our product specs, we can say item is equal to product. And then in our product specs HTML we can just rename all of the products to item, replace all of them, and then the specs should work just the same as well. Now our product specs directive is reusable outside of that ngRepeat too.
Again, the idea being that this reviewed product is set in our product tabs where reviewed product is assigned to product. This product comes from the repeater here and through our directive is where we defined the scope, which says use reviewed product as the name of the product that's going to be passed in, and use that object as an object to bind both ways to.
To demonstrate this, let's blow up our entire application and only show the tabs for the bloodstone, which means that we can delete everything except for the store controller. We'll need that for our product tabs. We'll pass in a tab product and assign that to store product and bloodstone is number one. We will refresh, and you can see that we get tabs for bloodstone. Specs and Reviews are all there, without any dependencies from our application other than some sort of product item being passed into our tabbed product.