Open the console here and let's go ahead and
try to click bad remove item number one.
When we click here we see that for some reason we
don't have any kind of announcement here what the last removed item was.
If we take a look at our console I think it's going to give us a clue.
This is, and remember this right now is being called from the remove item
method that is sitting on our controller that is the main controller and
if we take a look this is ShoppingListDirectiveController.
So it's not the shopping list controller,
it's shopping list directed controller which is not what we want because.
Because ShoppingListDirectiveController is the controller for our isolate scope and
we wanted this to execute in the parent controller's scope.
As you could see,
all these things that we thought were being assigned on the parent controller
scope are actually being assigned directly to our directives isolate scope.
And that's why you see that the title still says
list number 1 has 3 items in it, and so what happened to the title?
Well, when we said this.title and updated of the title with two items, it when had
and created that title, the title property on our ShoppingListDirectiveController.
Meanwhile the actual shopping list controller
doesn't know anything about this.
Let's go back to the code editor and
actually take a look as to why something like that is happening.
I actually created this this.html and it's just referencing this.js so
we will be able to see what's going on.
And here's a quick example on the microcosm as to what's going on
here in our controllers.
Suppose we have this function called Person and it says,
this.fullName is Yaakov, this.fav is Cookies.
And we have one method on the subject, which is the function and now what it's
doing is loading to the console and says, this.fullName likes this.fav.
If we now go ahead and create this yaakov object with the called the new person,
as we should,
that this variable inside of this object will be pointing to the person object.
And when we call yakov.describe,
in other words this method, this will still be pointing to the Person object,
and therefore, you'll be able to reference fullName and fave.
So let's go ahead and actually comment this out, for a second.
Let's go ahead and save that, and let's open this.html in the browser.
And you'll see that the console says, Yaakov likes cookies, very true.
Now if we go back, and go to this.js, what we're going to do now is we're going to
pull out the method from this yaakov object.
After all, yaakov.describe without the parenths is just a function value, so
we could grab that value and stick it in a local variable.
And then since that local variable is pointing to a function value,
we can actually execute it just by putting parenths behind it.
If we save that and go back to our browser, let's refresh that.
You can see it already says that undefined likes undefined.
How come this is going on?
Well, the reason this is going on is if we actually put a console.log right inside of
here, let's put a log statement here and say, what exactly is this variable?
Let's go ahead and say, this is, what is the this variable?
Let's go ahead and output this.
You could see that the first time we go around, this variable is the person but
the second time going around, this variable is actually the window.
And the window doesn’t have a full name and a fav.
The reason this is happening is because we took that method out of its context and
its context became the window,
because we were sitting after all in the global scope.
There is actually a java script solution to that and it's called the call method.
If you take the method that is out of context, in other words,
the this very well is pointing to whatever the surrounding context is.
You could actually give it context and basically it will get that
this variable assigned to whatever object that you're passing it in the call method.
So if we invoke describe with the call method and pass it to object yaakov then
this variable will all of a sudden once again be pointing to yaakov.
So if we save that and go back to our browser you'll see that even
though the first time it says undefined undefined the next time this is is
actually pointing back into Person and it actually will say, Yaakov likes cookies.
And this is what's happening in our controller.
If we go back,
we could close this now, what's happening in our controllers is that when this call
is being made right here, this call is being made just with a function reference.
It's like a variable that was yanked out of its context and
now sitting in a different context, in the case of the describe function
in our this example, it was sitting in the context of the window object.
Well, in the case of this badRemove example, it's sitting in the context
of the directives controller, not of the parent controller as we want it.
So the solution is, is to use the app reference and then pass a map
of arguments that is mapped to how we code this method, to begin with.
So let's go to app.gs and
what we're going to do now is we're going to declare yet another attribute.
And another attribute will be called onRemove.
And onRemove is going to have an ampersand binding
which means it's going to be a reference binding.
Will go to index.html and we'll add one more button here or
one more attribute and we'll call it on-remove and this time we'll call
list.remove item and will pass it in index.
Except as I told you as you remember
this index is not something that the ShoppingListController will be passing.
This index is just a key for our directive to be able to find and
assign some value to it so all of this will get executed in the context
of the ShoppingListController not of the ShoppingListDirectiveController.
Let's go ahead and actually put this back there.
It'll look a little bit better that way.
We'll go back to our shoppingList.html, that is the template for our directive.
Let's close the file browser so it'll be easier to see,
and we'll actually uncomment this button right here.
And if you take a look, it's list,
which is the list of my ShoppingListDirectiveController.
onRemove, that's the property we mapped on remove into the controller on our
Isolate Scope, and then you could see we're passing it an object that is a map.
It's mapping the index, if you take a look at the index.html,
this is the index that we're mapping.
So it's taking that index and
it's saying it should be equal to at the time you call this, it should be equal to
that'll assign index, which is the index through the loop at the moment.
Now when we save it and go back to the browser, we'll close our this example and
we'll close this as well.
And here is our directive with Isolate Scope, let's go ahead and add test,
well first of all it's not refreshing for some reason, let's refresh it, here we go.
Okay, so let's add our test 1, add 1, so we have bad remove and
with remove item will do test 2, add Item and test 3 and add that item.
And let's go ahead try to caught Removed Item.
Let's say Remove Test 2.
Request Removed Test 2 you'll see that the last item remove showed up here
which means that property did show up In the parent controller.
And if we take a look, in our remove item method,
we logged what the variable this pointed to.
In this case, it's pointing to the ShoppingListController which is
exactly what we wanted.
We wanted to execute that method In the context of the ShoppingListController
which is the parent of our directive.
And if we take a look all the things that we need are here and
we see are here and we see the last little property is here and
the shopping list title also got updated to two and therefore it's right there.
If we remove it again, this time we remove number 1, so it's number 1 and so on.
So this is working.
So once again, what allowed us to be able to call this method
in the context of the parent of this directive is the reference
that we declared onRemove property, which is the ampersand that is
giving us a reference to the function such that it's going to get executed
in its parent environment evaluating all the properties like they should be.