` and inserts that view in a
[_view container_](api/core/ViewContainerRef "API: ViewContainerRef")
adjacent to the directive's original `` host element.
You'll acquire the `` contents with a
[`TemplateRef`](api/core/TemplateRef "API: TemplateRef")
and access the _view container_ through a
[`ViewContainerRef`](api/core/ViewContainerRef "API: ViewContainerRef").
You inject both in the directive constructor as private variables of the class.
### The _appUnless_ property
The directive consumer expects to bind a true/false condition to `[appUnless]`.
That means the directive needs an `appUnless` property, decorated with `@Input`
Read about `@Input` in the [_Template Syntax_](guide/template-syntax#inputs-outputs) guide.
Angular sets the `appUnless` property whenever the value of the condition changes.
Because the `appUnless` property does work, it needs a setter.
* If the condition is falsy and the view hasn't been created previously,
tell the _view container_ to create the _embedded view_ from the template.
* If the condition is truthy and the view is currently displayed,
clear the container which also destroys the view.
Nobody reads the `appUnless` property so it doesn't need a getter.
The completed directive code looks like this:
Add this directive to the `declarations` array of the AppModule.
Then create some HTML to try it.
When the `condition` is falsy, the top (A) paragraph appears and the bottom (B) paragraph disappears.
When the `condition` is truthy, the top (A) paragraph is removed and the bottom (B) paragraph appears.
{@a directive-type-checks}
## Improving template type checking for custom directives
You can improve template type checking for custom directives by adding template guard properties to your directive definition.
These properties help the Angular template type checker find mistakes in the template at compile time, which can avoid runtime errors those mistakes can cause.
Use the type-guard properties to inform the template type checker of an expected type, thus improving compile-time type-checking for that template.
* A property `ngTemplateGuard_(someInputProperty)` lets you specify a more accurate type for an input expression within the template.
* The `ngTemplateContextGuard` static property declares the type of the template context.
This section provides example of both kinds of type-guard property.
For more information, see [Template type checking guide](guide/template-typecheck "Template type-checking guide").
{@a narrowing-input-types}
### Make in-template type requirements more specific with template guards
A structural directive in a template controls whether that template is rendered at run time, based on its input expression.
To help the compiler catch template type errors, you should specify as closely as possible the required type of a directive's input expression when it occurs inside the template.
A type guard function *narrows* the expected type of an input expression to a subset of types that might be passed to the directive within the template at run time.
You can provide such a function to help the type-checker infer the proper type for the expression at compile time.
For example, the `NgIf` implementation uses type-narrowing to ensure that the
template is only instantiated if the input expression to `*ngIf` is truthy.
To provide the specific type requirement, the `NgIf` directive defines a [static property `ngTemplateGuard_ngIf: 'binding'`](api/common/NgIf#static-properties).
The `binding` value is a special case for a common kind of type-narrowing where the input expression is evaluated in order to satisfy the type requirement.
To provide a more specific type for an input expression to a directive within the template, add a `ngTemplateGuard_xx` property to the directive, where the suffix to the static property name is the `@Input` field name.
The value of the property can be either a general type-narrowing function based on its return type, or the string `"binding"` as in the case of `NgIf`.
For example, consider the following structural directive that takes the result of a template expression as an input.
export type Loaded = { type: 'loaded', data: T };
export type Loading = { type: 'loading' };
export type LoadingState = Loaded | Loading;
export class IfLoadedDirective {
@Input('ifLoaded') set state(state: LoadingState) {}
static ngTemplateGuard_state(dir: IfLoadedDirective, expr: LoadingState): expr is Loaded { return true; };
export interface Person {
name: string;
}
@Component({
template: `{{ state.data }}
`,
})
export class AppComponent {
state: LoadingState;
}
In this example, the `LoadingState` type permits either of two states, `Loaded` or `Loading`. The expression used as the directive’s `state` input is of the umbrella type `LoadingState`, as it’s unknown what the loading state is at that point.
The `IfLoadedDirective` definition declares the static field `ngTemplateGuard_state`, which expresses the narrowing behavior.
Within the `AppComponent` template, the `*ifLoaded` structural directive should render this template only when `state` is actually `Loaded`.
The type guard allows the type checker to infer that the acceptable type of `state` within the template is a `Loaded`, and further infer that `T` must be an instance of `Person`.
{@a narrowing-context-type}
### Typing the directive's context
If your structural directive provides a context to the instantiated template, you can properly type it inside the template by providing a static `ngTemplateContextGuard` function.
The following snippet shows an example of such a function.
@Directive({…})
export class ExampleDirective {
// Make sure the template checker knows the type of the context with which the
// template of this directive will be rendered
static ngTemplateContextGuard(dir: ExampleDirective, ctx: unknown): ctx is ExampleContext { return true; };
// …
}
{@a summary}
## Summary
You can both try and download the source code for this guide in the .
Here is the source from the `src/app/` folder.
You learned:
* that structural directives manipulate HTML layout.
* to use [``](guide/structural-directives#ngcontainer) as a grouping element when there is no suitable host element.
* that the Angular desugars [asterisk (*) syntax](guide/structural-directives#asterisk) into a ``.
* how that works for the `NgIf`, `NgFor` and `NgSwitch` built-in directives.
* about the [_microsyntax_](guide/structural-directives#microsyntax) that expands into a [``](guide/structural-directives#template).
* to write a [custom structural directive](guide/structural-directives#unless), `UnlessDirective`.