I think the local provider for a directive is to provide services for its content children, for example:
//template in a module
<table>
<tr>
<td>{{ item.price | myPipe }}</td>
</tr>
</table>
myPipe
has a dependency of MyService
in its contructor:
So if I define a directive as:
@Directive({
selector: "[myAttr]",
providers: [MyService]
})
export class MyDirective { }
and apply it as:
<table>
<tr myAttr>
<td>{{ item.price | myPipe }}</td>
</tr>
</table>
then MyService
in myPipe
's constructor can be resolved.
But if there is a component also define MyService
in its local providers and apply it as:
<myComponent>
<tr myAttr>
<td>{{ item.price | myPipe }}</td>
</tr>
</myComponent>
since both the MyDirective
and MyComponent
can provider the service for myPipe
, so which one will myPipe
choose, local provider of MyDirective
or MyComponent
?
Every Component in Angular gets its very own Injector context, which is used to provide Services (or, more generally, Injectables) to itself and its component tree.
Pipes seem to always use the Injector context of the Component whose template they are in (empirically tested by me, citation needed). So if you have a Component (let's call it parentComponent
) with a template that looks like this:
<myComponent>
<tr myAttr>
<td>{{ item.price | myPipe }}</td>
</tr>
</myComponent>
then myPipe
will not get the Service instance from either myComponent
or myAttr
! So the direct answer to your question is neither!
Instead it will get the Service instance as used (provided) by the declaring Component (i.e. parentComponent
).
In terms of HTML structure it does indeed seem that myPipe
is a child of both myComponent
and myAttr
. However, in terms of Angular's hierarchy myPipe
is a child of parentComponent
and so it gets its service provider there. Also, pipes, unlike Components, are not affected by content projection (use of <ng-content>
).
It seems that your understanding of how services are provided is not quite right. Here are some corrections of the statements that you made:
Components behave differently from pipes. They form component trees and Injector contexts change accordingly. So if in place of myPipe
you had a yetAnotherComponent
, it would in fact get MyService as provided by myComponent
as opposed to parentComponent
.
If your directive provides a Service and you apply that Directive to a Component, that Component will get the Service as provided by the Directive! Unless, of course, it has registered a provider itself.