{"componentChunkName":"component---src-templates-blog-post-js","path":"/angular-structural-vs-attribute-directives/","result":{"data":{"site":{"siteMetadata":{"title":"Undefined","author":"Anirudh Varma"}},"markdownRemark":{"id":"8bbb7cb2-df8c-533f-8698-0fad87a403e3","excerpt":"Anyone who has worked with Angular would have used directives. According to the the official \nAngular documentation, there are 3 types of Directives: Components…","html":"<p>Anyone who has worked with Angular would have used directives. According to the the official\n<a href=\"https://angular.io/guide/attribute-directives#directives-overview\">Angular documentation</a>, there are 3 types of Directives:</p>\n<ul>\n<li>Components</li>\n<li>Structural Directives like <code class=\"language-text\">ngIf</code> and <code class=\"language-text\">ngFor</code></li>\n<li>Attribute Directives like <code class=\"language-text\">ngStyle</code></li>\n</ul>\n<p>This post primarily documents creating and using custom Structural Directives and how it differs with respect to the more commonly used attribute directive.</p>\n<h2 id=\"what-are-structural-directives\" style=\"position:relative;\"><a href=\"#what-are-structural-directives\" aria-label=\"what are structural directives permalink\" class=\"anchor-hint before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What are structural directives?</h2>\n<p>As the name suggests, structural directives are responsible for manipulating the DOM structure by adding, removing or changing the elements they are attached to. Perhaps the most common structural directive most Angular developers use the <code class=\"language-text\">ngIf</code> directive, which is used to show/hide the elements based on a boolean condition.</p>\n<blockquote>\n<p>Beginner tip: The structural directives are prefixed with a <code class=\"language-text\">*</code> while attribute directives may be used just by adding their selector as an attribute to the element. </p>\n</blockquote>\n<h2 id=\"creating-your-own-structural-directive\" style=\"position:relative;\"><a href=\"#creating-your-own-structural-directive\" aria-label=\"creating your own structural directive permalink\" class=\"anchor-hint before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Creating your own structural directive.</h2>\n<p>Lets assume that you have a payment configuration based on which you want to show or hide certain elements for certain users. We will create a directive, which will take an input for a feature flag and then show or hide the element based on the payment configuration.</p>\n<p>Creating a structural directive is pretty similar to creating an attribute directive.</p>\n<div class=\"gatsby-highlight\" data-language=\"typescript\"><pre class=\"language-typescript\"><code class=\"language-typescript\"><span class=\"token decorator\"><span class=\"token at operator\">@</span><span class=\"token function\">Directive</span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> selector<span class=\"token operator\">:</span> <span class=\"token string\">'[appRenderIfEnabled]'</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">RenderFeatureDirective</span> <span class=\"token keyword\">implements</span> <span class=\"token class-name\">OnInit</span><span class=\"token punctuation\">{</span>\n\n    <span class=\"token keyword\">private</span> flag<span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token decorator\"><span class=\"token at operator\">@</span><span class=\"token function\">Input</span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">set</span> <span class=\"token function\">appRenderIfEnabled</span><span class=\"token punctuation\">(</span>flag<span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>flag <span class=\"token operator\">=</span> flag<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span>\n        <span class=\"token keyword\">private</span> templateRef<span class=\"token operator\">:</span> TemplateRef<span class=\"token operator\">&lt;</span><span class=\"token builtin\">any</span><span class=\"token operator\">></span><span class=\"token punctuation\">,</span>\n        <span class=\"token keyword\">private</span> viewContainer<span class=\"token operator\">:</span> ViewContainerRef<span class=\"token punctuation\">,</span>\n        <span class=\"token keyword\">private</span> configService<span class=\"token operator\">:</span> ConfigService\n    <span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>\n\n    <span class=\"token function\">ngOnInit</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>configService<span class=\"token punctuation\">.</span><span class=\"token function\">isEnabled</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>flag<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">subscribe</span><span class=\"token punctuation\">(</span>enabled<span class=\"token operator\">=></span><span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span>enabled<span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n                <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>\n            <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n                <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>\n            <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>As you can see, the directive takes one input, the name of which must match with the selector that you choose (appRenderIfEnabled) in this case.\nThe directive gets the reference to a <code class=\"language-text\">TemplateRef</code> and a <code class=\"language-text\">ViewContainer</code>, this is because a directive creates an embedded view inside the given <code class=\"language-text\">ViewContainer</code> and the <code class=\"language-text\">TemplateRef</code> is used to access the contents of the template/element the directive is attached to.</p>\n<p>Now the custom directive is ready to be used, add it to any component like: </p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>my-pro-version-component</span> <span class=\"token attr-name\">*appRenderIfEnabled</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token punctuation\">'</span>PRO_PACKAGE_ONLY<span class=\"token punctuation\">'</span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>my-pro-version-component</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<h2 id=\"using-additional-input-with-your-directive\" style=\"position:relative;\"><a href=\"#using-additional-input-with-your-directive\" aria-label=\"using additional input with your directive permalink\" class=\"anchor-hint before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Using additional @Input with your directive.</h2>\n<p>Till now, our directive is just taking the flag as an input, but what if you want to be able to provide a default value incase of missing configuration?</p>\n<p>The key part of having additional inputs in structural directives is that the name of the input property must be prefixed with the selector. In our case, we want a <code class=\"language-text\">defaultConfig</code>, so the name of the input property would be <code class=\"language-text\">appRenderIfEnabledDefaultConfig</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"typescript\"><pre class=\"language-typescript\"><code class=\"language-typescript\"><span class=\"token decorator\"><span class=\"token at operator\">@</span><span class=\"token function\">Directive</span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> selector<span class=\"token operator\">:</span> <span class=\"token string\">'[appRenderIfEnabled]'</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">RenderFeatureDirective</span> <span class=\"token keyword\">implements</span> <span class=\"token class-name\">OnInit</span><span class=\"token punctuation\">{</span>\n\n    <span class=\"token keyword\">private</span> flag<span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">private</span> defaultConfig <span class=\"token operator\">=</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token decorator\"><span class=\"token at operator\">@</span><span class=\"token function\">Input</span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">set</span> <span class=\"token function\">appRenderIfEnabled</span><span class=\"token punctuation\">(</span>flag<span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>flag <span class=\"token operator\">=</span> flag<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">// must be prefixed with selector</span>\n    <span class=\"token decorator\"><span class=\"token at operator\">@</span><span class=\"token function\">Input</span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">set</span> <span class=\"token function\">appRenderIfEnabledDefaultConfig</span><span class=\"token punctuation\">(</span>conf<span class=\"token operator\">:</span><span class=\"token builtin\">boolean</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>defaultConfig <span class=\"token operator\">=</span> conf<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span></code></pre></div>\n<p>The new input can be simply added using the following syntax:</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>my-pro-version-component</span> <span class=\"token attr-name\">*appRenderIfEnabled</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token punctuation\">'</span>PRO_PACKAGE_ONLY<span class=\"token punctuation\">'</span>;defaultConfig: true<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>my-pro-version-component</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<h3 id=\"useful-links--\" style=\"position:relative;\"><a href=\"#useful-links--\" aria-label=\"useful links   permalink\" class=\"anchor-hint before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Useful links -</h3>\n<ul>\n<li><a href=\"https://angular.io/guide/attribute-directives#directives-overview\">Official Documentation for Directives</a></li>\n<li><a href=\"https://angular.io/guide/structural-directives#write-a-structural-directive\">Official Documentation for creating Structural Directives</a></li>\n</ul>","frontmatter":{"title":"Strucural vs Attribute Directives in Angular","date":"January 03, 2019","ogimage":null}}},"pageContext":{"slug":"/angular-structural-vs-attribute-directives/","previous":{"fields":{"slug":"/bolt-content-and-relations/"},"frontmatter":{"title":"Bolt CMS: Using content types and relations"}},"next":{"fields":{"slug":"/align-items-vs-content-flexbox/"},"frontmatter":{"title":"Flexbox - Align Items vs Align Content."}}}},"staticQueryHashes":["426816048","983108779"]}