Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

186
Views
Choose between 2 Angular components on the module

I have an Angular project used by some clients. So, every time I build the project I do it for one client, changing a property on a configuration file. Also, I may have slightly different logic on some components for different clients. For instance:

@Component({
  selector: 'my-component',
  templateUrl: './component.template.html',
  styleUrl: './component.styles.scss'
})
export class MyBaseComponent {
  getName() {
    return 'Base';
  }

  /* Other logic here ... */
}

@Component({
  selector: 'my-component',
  templateUrl: './component.template.html',
  styleUrl: './component.styles.scss'
})
export class MyClientComponent extends MyBaseComponent {
  getName() {
    return 'Client';
  }
} 

@Component({
  selector: 'my-component',
  templateUrl: './component.template.html',
  styleUrl: './component.other-client.styles.scss'
})
export class MyOtherClientComponent extends MyBaseComponent {
  getName() {
    return 'Other Client';
  }
} 

Now, what I would like is for this to be totally transparent for other modules that import this components. Note that all three selectors are named the same. I tried to implement the module like this:

import { client } from '../environment';
import { MyBaseComponent, MyClientComponent, MyOtherClientComponent } from './components';

function chooseComponent() {
  switch(client) {
    case 'my-client':
      return MyClientComponent;
    case 'my-other-client':
      return MyOtherClientComponent;
    default:
      return MyBaseComponent;
  }
}

@NgModule({
  declarations: [chooseComponent()],
  imports: [],
  providers: [],
  exports: [chooseComponent()],
})
export class TestComponentModule {}

But Angular does not let me do this. Do you guys know what's the correct way to implement this. Sure, I could use and if to change the logic. But that's ugly.

Also, if I would like to change a piece of the html template, based on the client. What would be the best to do it? Imagine, if client is X I show a button, and if its Y I show label. Is using ngIf the only way?

Thanks!

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

There are several ways to do this. 1- you could create a container component and use ngSwitch in the template. In this case you would need to use a unique selector for each component and use it in the container component template: e.g.

Container Template

<ng-container [ngSwitch]="client">
  <my-client-component *ngSwitchCase="'my-client'"></my-client-component>
  <my-other-client-component *ngSwitchCase="'my-other-client'"></my-other-client-component>
</ng-container>

2- You could use dynamic rendering and do the magic in your container component typescript file. You could define a method with switch on client variable and let angular render the component in the view based on the client. For more details about how to render a dynamic component see the angular dynamic component render documentation. In case you do not want to load the other client component to the browser, you could put your components in a lazy module and import them with dynamic import. See this nice article https://medium.com/@ckyidr9/lazy-load-feature-modules-without-routing-in-angular-9-ivy-220851cc7751

over 4 years ago · Santiago Trujillo Report

0

If am not wrong, you can do this in quite a few ways:

  1. Using RouteGuard and lazyloading: That would look like this:
// Have each component in 3 different modules. Have 3 route guards and use them to load the exact module. Something like this: 

import { ActivatedRouteSnapshot, RouterStateSnapshot, CanActivate } from '@angular/router';
import { client } from '../environment';

@Injectable()
export class MyClientGuard implements CanActivate {
  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): boolean {
    return client === 'my-client';
  }
}

@Injectable()
export class MyOtherClientGuard implements CanActivate {
  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): boolean {
    return client === 'my-other-client';
  }
}

@Injectable()
export class MyBaseComponentGuard implements CanActivate {
  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): boolean {
    return (client !== 'my-client' || client !== 'my-other-client');
  }
}

const routes: Routes = [
  {
    path: 'base-component',
    loadChildren: () => import('./base-component/base-component.module').then(m => m.BaseComponentModule),
    canActivate: [MyBaseComponentGuard]
  },
  {
    path: 'other-client',
    loadChildren: () => import('./other-client/other-client.module').then(m => m.OtherClientModule),
    canActivate: [MyOtherClientGuard]
  },
  {
    path: 'my-client',
    loadChildren: () => import('./my-client/my-client.module').then(m => m.MyClientModule),
    canActivate: [MyClientGuard]
  }
];
  1. Second way of doing this is: Using Resolvers. You may refer to this documentation for more details on resolvers: https://angular.io/api/router/Resolve Have not used this much but might help you.

  2. Third way is having everything in a single module and single component and based on environment.client value, using ngIf / ngtemplate to show the correct templates in the page.

  3. One more way is use the same component and define some @Input() clientValue: string input value like that and based on that you can show hide values using ng-container and ng-template.

over 4 years ago · Santiago Trujillo Report

0

Not directly related but you could have a look at this app I built some time ago https://stackblitz.com/edit/angular-rxjs-in-memory-caching-dynamic?file=src%2Fapp%2Froot.component.ts

This simulates a dashboard with widgets where data for the widget is retrieved from the server, the API simulates random delays on each call and caches the API calls in the browser.

In terms of configuration, you can see how you can define what widgets you want to see on the page, it uses the dynamics component loader to load the components. This was built in Angular 8, there are more elegant ways to do this with Ivy from Angular 9

enter image description here

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!