title: How to manage separation of concerns with multiple custom directives in Angular?
body: <p><strong>Feature based visibility in the app</strong><br />
  I'm working on a solution in a large-scale angular application to manage the availability of components to users regarding their features that they bought. So the users don't have all the features of the application by default, but only the features that they have purchased.</p>
  <p><strong>Feature and permission based visibility in the same app</strong><br />
  The app already has a role/permission based visibility management of components. I add new feature based visibility besides it, but to separate the concerns I don't want to mix the new ones logic into the current one.</p>
  <hr />
  <p>Say the whole app having 50 features in total and [A-Z] components/pages belongs them:</p>
  <pre><code>Feature1 //not a module! conceptual feature that I have mentioned. Think as new dimension besides role/permission
    -PageComponentA   //Permission/role based management in it also
    -PageComponentB   //role based visibility again
  Feature2
    -PageComponentC   //role check
    -PageComponentD   //same
    -PageComponentE   //...
  ...
  Feature50
    -PageComponentZ
    -PageComponentX
  </code></pre>
  <p>I have created a <code>FeatureDirective</code> with an input to map components to the items in a feature set.</p>
  <pre class="lang-js prettyprint-override"><code>@Directive({
    selector: '[appFeature]'
  })
  export class FeatureDirective {
    @Input() itemKey: string;
    featureList: any[] = [];
    constructor(private templateRef: TemplateRef&lt;any&gt;, private viewContainer: ViewContainerRef, private FeaturesService: FeatureService,private applicationRef: ApplicationRef) {
        
    }
    ngOnInit() {
      setTimeout(()=&gt;{   //this one I have found as a solution to set order between multiple directives but not works 
        console.log(`feature directive processing`); 
        this.isFeatureAvailableWithExpiry();
        this.applicationRef.tick();
      }, 1000);  
    }
  
     isFeatureAvailable() {      
      this.FeaturesService.getToken().pipe(
        mergeMap(token =&gt; this.FeaturesService.getFeatures(&quot;userxxx&quot;, &quot;otheruserinputyyy&quot;, token))
      ).subscribe((features: any[]) =&gt; {
        let feature = FEATURES.filter(FEATURE =&gt; features.some(feature =&gt; FEATURE.Code === feature.code))
                              .find(FEATURE =&gt; FEATURE.ItemKey === this.itemKey);
        if(feature) {
          if(feature.status) {
            this.viewContainer.createEmbeddedView(this.templateRef);
          } else {
            this.viewContainer.clear();
          }
        }
      }, 
        err =&gt; console.log(err) 
      );
    }
  </code></pre>
  <p>Then in a page component I have mapped component to the directive.</p>
  <pre class="lang-html prettyprint-override"><code>//view template starts here...
  &lt;ng-template appFeature appPermission [itemKey]=&quot;'milkingSettings'&quot; [itemType]=&quot;'view'&quot;&gt;
  ...
  &lt;/ng-template&gt;
  </code></pre>
  <pre class="lang-js prettyprint-override"><code>@Directive({
    selector: '[appPermission]'
  })
  export class PermissionDirective {
    @Input() itemKey: string;
    @Input() itemType: string;
    constructor(private element: ElementRef, private templateRef: TemplateRef&lt;any&gt;, private viewContainer: ViewContainerRef, private ApiService: ApiService) {
  
    }
  
    ngOnInit() {
      let userInfo = this.ApiService.getUserInfo();
  
      (async () =&gt; {
        let access = await this.ApiService.getPermission(this.itemKey, userInfo.RoleId);
        if (this.itemType == &quot;view&quot; &amp;&amp; access &amp;&amp; access.view) {
          this.viewContainer.createEmbeddedView(this.templateRef);
        } else if (this.itemType == &quot;action&quot; &amp;&amp; access &amp;&amp; access.action) {
          this.viewContainer.createEmbeddedView(this.templateRef);
        } else {
          this.viewContainer.clear();
        }
      })();
    }
  }
  
  </code></pre>
  <p>The problem is like seen above there is also a permission directive which has the same mechanism to show/hide the components according to the role of user logged in. So the question arises is in this setup I need to set a priority against this multiple custom directives since feature check should run first and then role check should happen.</p>
  <p>I have found that there is no mechanism to directly set the load/run order of the multiple custom directives, but there are maybe some workarounds like <code>setTimeout(..., 0)</code> or using <code>ApplicationRef.tick()</code> which I'm not sure how exactly.</p>
  <p>While thinking about order and the fact that this may not be a best practice since Angular deliberately remove the priority concept, I start to think about whether my solution which is creating a new directive regarding separation of concerns is suitable one or not.</p>
  <p>My considerations are:</p>
  <ol>
  <li>Provide <code>SoC</code></li>
  <li>(Nearly) All the templates already have permission directive so if I create new feature directive then there will be 100+ template source changes just to add feature directive in my current solution</li>
  <li>Managing multiple custom directive priority/order in my current solution</li>
  </ol>
  <p>Instead of my solution should I just use the current by putting the feature check logic in <code>PermissionDirective</code> also and change its name <code>FeaturePermissionDirective</code>? So I don't have to manage priority and change all the template source files just to add new directive. Is there any other way to provide <code>SoC</code> but also changing all the templates in this scenario and not using multiple directives?</p>