I'm personally not a fan of calling a function on the parent or root or stuff like that, as its coupled in a kind of implicit way. I prefer to use a service as you mentioned or injecting the concrete function(s) into your directive.
Below are some pros and cons for both approaches. Please note they are based on my personal experience (and I'm not an expert).
Services
Services are singletons, meaning there is only one instance in your whole application. This can have several advantages, if you need them:
- it's always there (you don't need to create it explicitly)
- it can cache data which can be usefull, e.g. to maintain the state of a view/page
- it can be used to exchange data between different components
- it can easily be injected where ever you need it
This can also lead to some disadvantages though:
- if different components share the same service, they might mess up each others data
- components (i.e. directives) will depend on that service, leaving the user of the directive no flexibility in how he wants to use that directive (e.g. what should happen when a user clicks a button). Meaning that basically the concrete functionality is "hard-coded" in to the directive.
I personally like to use services, if they have a direct link to the directive (and to nothing else) or do not store any state, for example if they only contain simple helper functions.
If in your application you have one conversation list, then I would consider implementing that in a service that exposes functions like addMessage
, deleteMessage
, sortBy
, etc.. Then it can be injected in to any component which needs access to that (central) list.
Passing functions as arguments
On the other hand, if you have a message
-directive, you might want to use it for other kind of messages as well..? That is messages which are not from the conversation
but maybe from a mailbox
(just a stupid example ;)). Then I wouldn't couple the service and the directive. You could inject the deleteMessage
-function, which in one case would remove it from the conversation
and in the other case remove it from the mailbox
.
I think both approaches are valid, but always depend on the scenario and how the components are shared/reused over your application.
The second approach might be nicer from a "coupling"-perspective, but might get complicated in case of lots of parameters and when passing parameters over several levels of components (e.g. to child-child-child directives).
The first approach is easy to implment and can have several advantages, but results in the component being directly coupled to that service, lowering its reusability.