Angular Context: Easy property binding for router outlet and nested component trees.
npm install ngx-contextAngular Context is a library to bind data to deeply nested child components without passing properties through other components or getting blocked by a router outlet.
If you would like to have further information on why you need a library like this, you may find the reasons below. Otherwise, skip to the quickstart or usage section.
Check demo application out for a preview.
You may also find the introductory blog post helpful.
Data-binding and input properties are great. However, working with them has some challenges:
- Passing properties through several layers of the component tree is known as prop-drilling and it is time consuming and error prone to maintain.
- The intermediary components become bloated with properties and methods just to pass data from parent to child and vice versa.
- When a component is loaded via router-outlet, data-binding is not available and prop-drilling is no longer an option.
This library is designed to improve developer experience by fixing all issues above. It provides context through dependency injection system behind-the-scenes and lets your deeply nested dumb components consume this context easily. It is inspired by React Context, but differs in implementation and is 100% tailored for Angular.

Run the following code in your terminal:
```
yarn add ngx-context
or if you are using npm:
``
npm install ngx-context
Import NgxContextModule into your root module like:
`TS
import { NgxContextModule } from 'ngx-context';
@NgModule({
imports: [ NgxContextModule ]
})
export class AppModule {}
`
Simply put a ContextProviderComponent around the children and refer to property names to provide.
`TS
@Component({
selector: 'parent-component',
template:
,
})
export class ParentComponent {
someProp: string = 'Test';
someOtherProp: boolean = true;
notProvided: number = 5;
alsoNotProvided: Observable<> = empty();
}
`
You may consume any provided context in a component by placing a ContextConsumerDirective on it. This component can either be a direct or a deeply nested child of the context provider.
`HTML
`
The name of the props to be provided is set by provide input and it can take string or Array values.
`HTML
`
— or —
`HTML
`
Provided property names can be dynamically set.
`HTML
`
Provided property names can be mapped.
`HTML
[contextMap]="{someProp: 'someOtherPropName'}"
>
`
Context consumers or their parents should be wrapped by ContextProviderComponent in the parent component.
`HTML
`
More than one ContextProviderComponent can be placed in a parent component.
`HTML
`
Router outlets have no effect on context and can be safely used.
`HTML
`
The easiest way to consume a context is to place a ContextConsumerComponent inside a child component. It will be able to consume context once provided and behave normally when not.
`HTML
`
The name of specific props to be consumed can be set by consume input and it can take string or Array values.
`HTML
`
— or —
`HTML
`
Consumed property names can be dynamically set.
`HTML
`
Consumed property names can be mapped.
`HTML
`
If a component cannot take ContextConsumerComponent in (e.g. 3rd-party components), you can use ContextConsumerDirective on them.
`HTML
`
The name of specific props to be consumed can be set by contextConsumer input and it can take string or Array values.
`HTML
`
— or —
`HTML
`
Consumed property names can be dynamically set.
`HTML
`
Consumed property names can be mapped.
`HTML
`
There are some cases where you will need the context on a higher level and end up putting properties on a middle component's class. For example, in order to make reactive forms work, a ContextConsumerComponent will most likely be used and the consumed properties will have to be added to the wrapper component. This is usually not the preferred result. After all, we are trying to keep intermediary components as clean as possible. In such a case, you can use ContextDisposerDirective on an and make use of template input variables.
`HTML
`
The name of specific props to be disposed can be set by contextDisposer input and it can take string or Array values.
`HTML
[prop2]="context.someOtherProp"
>
`
— or —
`HTML
[prop2]="context.someOtherProp"
>
`
Properties to dispose can be dynamically set.
`HTML
[prop2]="context.someOtherProp"
>
`
Disposed property names can be individually assigned to template input variables.
`HTML
let-prop1="someProp"
let-prop2="someOtherProp"
>
``
Note: If you are wondering how you can implement reactive forms using Angular Context, please refer to the demo application.
There are several issues which are simply not addressed yet or impossible with currently available tools.
- There can be only one provider for any component sub-tree, altough using a provider in combination with a consumer would help transfer parent provider down the tree.
- Several consumers can consume the same provider, but a consumer can only have one provider (first provider up the tree).
- There is a performance penalty to be paid due to use of getters and setters. Although this penalty is kept as small as possible, it is not benchmarked yet.
- Debugging may become more difficult for child components, because their behavior will be defined by the context magically provided by some parent. ¯\\\_(ツ)\_/¯
- [x] Component to provide context
- [x] Component and directive to consume context
- [x] Directive to dispose context
- [x] Test coverage
- [x] Documentation & examples
- [x] Permissive license
- [x] Inclusive code of conduct
- [x] Issue submission templates
- [x] Contribution guidelines
- [x] CI integrations
- [ ] Benchmarks
- [ ] Optimization