Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

187
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda