Structural directives change the DOM layout by adding and removing DOM elements.
DOM in Javascript stands for Document Object Model , roughly translated as the model of objects in HTML documents.
Through the DOM model, we can access HTML tags easily. (You can learn more about the DOM online).
Angular has provided a set of built-in structural directives (such as NgIf , NgForOf , NgSwitch and others) that are commonly used in all Angular projects.
When structural directives are applied, they are usually prefixed with an asterisk, * , such as *ngIf.
Creating a structural directive
In this section we will create an UnlessDirective , this directive is responsible for showing or hiding a piece of text based on the value of the condition property in the AppComponent .
UnlessDirective does the opposite of NgIf and the values of the condition attribute can be set to true or false . UnlessDirective will display content when condition is false .
- First we use the command below to create a structural directive named unless
1 2 |
ng generate directive unless |
2.Continue to import Input , TemplateRef , and ViewContainerRef .
src/app/unless.directive.ts
1 2 3 4 5 6 |
<span class="token keyword">import</span> <span class="token punctuation">{</span> Directive <span class="token punctuation">,</span> Input <span class="token punctuation">,</span> TemplateRef <span class="token punctuation">,</span> ViewContainerRef <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@angular/core'</span> <span class="token punctuation">;</span> @ <span class="token function">Directive</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> selector <span class="token operator">:</span> <span class="token string">'[appUnless]'</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">UnlessDirective</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> |
3.Insert TemplateRef and ViewContainerRef in directive constructor as private variables.
src/app/unless.directive.ts
1 2 3 4 |
<span class="token function">constructor</span> <span class="token punctuation">(</span> <span class="token parameter"><span class="token keyword">private</span> templateRef <span class="token operator">:</span> TemplateRef <span class="token operator"><</span> any <span class="token operator">></span> <span class="token punctuation">,</span> <span class="token keyword">private</span> viewContainer <span class="token operator">:</span> ViewContainerRef</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> |
TemplateRef helps you to access <ng-template> content and ViewContainerRef accesses the view container.
4. Add the appUnless @Input () property with a setter.
src/app/unless.directive.ts
1 2 3 4 5 6 7 8 9 10 |
@ <span class="token function">Input</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">set</span> <span class="token function">appUnless</span> <span class="token punctuation">(</span> <span class="token parameter">condition <span class="token operator">:</span> boolean</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> condition <span class="token operator">&&</span> <span class="token operator">!</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> hasView <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> viewContainer <span class="token punctuation">.</span> <span class="token function">createEmbeddedView</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> templateRef <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> hasView <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> condition <span class="token operator">&&</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> hasView <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> viewContainer <span class="token punctuation">.</span> <span class="token function">clear</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> hasView <span class="token operator">=</span> <span class="token boolean">false</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Angular sets the appUnless property whenever the value of the condition changes.
– If condition is false and Angular has not created the view before, the viewContainer setter will create the embedded view(createEmbeddedView ) from the template
– If condition is true and the view is currently displayed, the setter will clear the container, discarding the view
Update the full code as follows:
src/app/unless.directive.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<span class="token keyword">import</span> <span class="token punctuation">{</span> Directive <span class="token punctuation">,</span> Input <span class="token punctuation">,</span> TemplateRef <span class="token punctuation">,</span> ViewContainerRef <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@angular/core'</span> <span class="token punctuation">;</span> <span class="token comment">/** * Add the template content to the DOM unless the condition is true. */</span> @ <span class="token function">Directive</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> selector <span class="token operator">:</span> <span class="token string">'[appUnless]'</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">UnlessDirective</span> <span class="token punctuation">{</span> <span class="token keyword">private</span> hasView <span class="token operator">=</span> <span class="token boolean">false</span> <span class="token punctuation">;</span> <span class="token function">constructor</span> <span class="token punctuation">(</span> <span class="token parameter"><span class="token keyword">private</span> templateRef <span class="token operator">:</span> TemplateRef <span class="token operator"><</span> any <span class="token operator">></span> <span class="token punctuation">,</span> <span class="token keyword">private</span> viewContainer <span class="token operator">:</span> ViewContainerRef</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> @ <span class="token function">Input</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">set</span> <span class="token function">appUnless</span> <span class="token punctuation">(</span> <span class="token parameter">condition <span class="token operator">:</span> boolean</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> condition <span class="token operator">&&</span> <span class="token operator">!</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> hasView <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> viewContainer <span class="token punctuation">.</span> <span class="token function">createEmbeddedView</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> templateRef <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> hasView <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> condition <span class="token operator">&&</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> hasView <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> viewContainer <span class="token punctuation">.</span> <span class="token function">clear</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> hasView <span class="token operator">=</span> <span class="token boolean">false</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Testing the directive
1.Update code file src/app/app.component.ts
Add a condition set to false in AppComponent.
1 2 |
condition <span class="token operator">=</span> <span class="token boolean">false</span> <span class="token punctuation">;</span> |
2. Update template to use directive. Here, appUnless is on top of two <p> tags with opposing condition values, one true and one false .
src/app/app.component.html
1 2 3 4 5 6 7 8 9 |
<span class="token operator"><</span> p <span class="token operator">*</span> appUnless <span class="token operator">=</span> <span class="token string">"condition"</span> <span class="token keyword">class</span> <span class="token operator">=</span> <span class="token string">"unless a"</span> <span class="token operator">></span> <span class="token punctuation">(</span> <span class="token constant">A</span> <span class="token punctuation">)</span> This paragraph is displayed because the condition is <span class="token boolean">false</span> <span class="token punctuation">.</span> <span class="token operator"><</span> <span class="token operator">/</span> p <span class="token operator">></span> <span class="token operator"><</span> p <span class="token operator">*</span> appUnless <span class="token operator">=</span> <span class="token string">"!condition"</span> <span class="token keyword">class</span> <span class="token operator">=</span> <span class="token string">"unless b"</span> <span class="token operator">></span> <span class="token punctuation">(</span> <span class="token constant">B</span> <span class="token punctuation">)</span> Although the condition is <span class="token boolean">true</span> <span class="token punctuation">,</span> <span class="token keyword">this</span> paragraph is displayed because appUnless is <span class="token keyword">set</span> to <span class="token boolean">false</span> <span class="token punctuation">.</span> <span class="token operator"><</span> <span class="token operator">/</span> p <span class="token operator">></span> |
The * in front of appUnless to represent appUnless as a structural directive
When the condition is false, the top fragment (A) appears and the bottom fragment (B) disappears.
When the condition is true, the top fragment (A) disappears and the bottom fragment (B) appears.
That’s the end of the post, hope the article is useful to you!