Ok, let's walk through why accessing the DOM from your controllers or controllers from
your directives are bad ideas. In the process, I will also explain what the changes I made are, and how you can
find out what they are for yourself in the future. Finally, I will explain how having a directive directly modify scope
in the way that Howard has recommended, while something that I did a few times when I was first learning Angular,
makes things harder for you in the long run.
Two of they key pillars of Angular app design are testability and separation of concerns. They go hand in hand,
because in order to have a well tested app, it should be easy to test, and to be easy to test you need to have a
good separation of concerns. For this reason, absolutely all DOM interaction should happen in directives.
When you're testing a directive, it's usually as easy as something like this:
var element = angular.element('<div my-directive></div>');
element.keyDown({...});
expect(element...
As you can see, by keeping all of your DOM interactions limited to happening in directives, you can very easily
test them without ever attaching them to the DOM itself, making it very easy to test in isolation. Striving for testable
code also usually results in directives that do very little (so that they are easy to test in completion), which often
leads to writing reusable, modular code.
However, if you want to write code that is useful outside of your own app, and resilient to being moved from place to
place within your own app, you need to make sure that your directives don't assume anything about the context in
which they will be run. This includes reading from / writing to the scope (unless it is an isolate scope, more on this
later), or accessing the active controller (unless it is a directive controller, which is just a way for directives to depend
upon and communicate with one another). But how do we get information from our DOM interactions to our app code?
You can use events, as you have done here, but that's a pretty blunt tool. Because of the way that scopes work,
it is impossible to prevent an event that is crawling down the scope tree (to the leaves) from propagating further, so
events are really only useful when you want multiple pieces of your application to be able to respond to the event. And
because we're doing our best to avoid assuming the context in which our directives will be used, we can't assume that
is the case, so we turn to another option.
You could write directly to the active scope and rely on the controller to $watch or otherwise react to those changes, but
again, this assumes an awful lot about the directive's context - what if I want to move this to a different controller that
doesn't have the same methods implemented or with a different signature? What if there is a name conflict with an existing
value on the scope? (My experience has dictated that, while often very useful and the only way to do things, $watch is a
code smell and if you find yourself reaching for it you should consider whether there's an easier way.)
Lastly, you can take advantage of isolate scopes and declare your wiring in the view/template. That's what I did in the
example I sent you.
....