# Component Replacement
You can replace some ABP components with your custom components.
The reason that you **can replace** but **cannot customize** default ABP components is disabling or changing a part of that component can cause problems. So we named those components as _Replaceable Components_.
## How to Replace a Component
Create a new component that you want to use instead of an ABP component. Add that component to `declarations` and `entryComponents` in the `AppModule`.
Then, open the `app.component.ts` and execute the `add` method of `ReplaceableComponentsService` to replace your component with an ABP component as shown below:
```js
import { ReplaceableComponentsService } from '@abp/ng.core'; // imported ReplaceableComponentsService
import { eIdentityComponents } from '@abp/ng.identity'; // imported eIdentityComponents enum
//...
@Component(/* component metadata */)
export class AppComponent {
constructor(
private replaceableComponents: ReplaceableComponentsService, // injected the service
) {
this.replaceableComponents.add({
component: YourNewRoleComponent,
key: eIdentityComponents.Roles,
});
}
}
```

## How to Replace a Layout
Each ABP theme module has 3 layouts named `ApplicationLayoutComponent`, `AccountLayoutComponent`, `EmptyLayoutComponent`. These layouts can be replaced the same way.
> A layout component template should contain `` element.
The example below describes how to replace the `ApplicationLayoutComponent`:
Run the following command to generate a layout in `angular` folder:
```bash
yarn ng generate component my-application-layout
```
Add the following code in your layout template (`my-application-layout.component.html`) where you want the page to be loaded.
```html
```
Open `app.component.ts` in `src/app` folder and modify it as shown below:
```js
import { ReplaceableComponentsService } from '@abp/ng.core'; // imported ReplaceableComponentsService
import { eThemeBasicComponents } from '@abp/ng.theme.basic'; // imported eThemeBasicComponents enum for component keys
import { MyApplicationLayoutComponent } from './my-application-layout/my-application-layout.component'; // imported MyApplicationLayoutComponent
@Component(/* component metadata */)
export class AppComponent {
constructor(
private replaceableComponents: ReplaceableComponentsService, // injected the service
) {
this.replaceableComponents.add({
component: MyApplicationLayoutComponent,
key: eThemeBasicComponents.ApplicationLayout,
});
}
}
```
> If you like to replace a layout component at runtime (e.g: changing the layout by pressing a button), pass the second parameter of the `add` method of `ReplaceableComponentsService` as true. DynamicLayoutComponent loads content using a router-outlet. When the second parameter of the `add` method is true, the route will be refreshed, so use it with caution. Your component state will be gone and any initiation logic (including HTTP requests) will be repeated.
### Layout Components

### How to Add a New Layout Component
To add a new layout component, you need to follow these steps:
#### Step 1: Create a New Angular Component
This component should have a 'router-outlet' for dynamic content loading. You can create a new component using the Angular CLI. Run the following command in your terminal:
```bash
ng generate component new-layout
```
This command will create a new component named `new-layout`. Now, open the new-layout.component.html file and add a `router-outlet` to it:
```html
```
This 'router-outlet' will act as a placeholder that Angular dynamically fills based on the current router state.
note: (don't forget: you should add the app in the app.module.ts file)
#### Step 2: Define a Variable for the Layout Component
Although this step is optional, it can be useful if you're going to use the layout component's value multiple times. You can define a variable for the layout component like this:
```javascript
export const eCustomLayout = {
key: "CustomLayout",
component: "CustomLayoutComponent",
};
```
In this variable, `key` is a unique identifier for the layout component, and `component` is the name of the layout component.
You can use this variable when you need to refer to the layout component.
#### Step 3: Add the Layout Component to the ABP Replaceable-System
Next, you need to add the new layout component to the `ReplaceableComponentsService`. This service allows you to replace a component with another one dynamically.
You can do this by defining a provider for `APP_INITIALIZER` that uses a factory function. In this function, you inject the `ReplaceableComponentsService` and use its `add` method to add the new layout component.
Here's how you can do it:
```javascript
export const CUSTOM_LAYOUT_PROVIDERS = [
{
provide: APP_INITIALIZER,
useFactory: configureLayoutFn,
deps: [ReplaceableComponentsService],
multi: true,
},
];
function configureLayoutFn() {
const service = inject(ReplaceableComponentsService);
return () => {
service.add({
key: eCustomLayout.component,
component: CustomLayoutComponent,
});
};
}
```
In this code, `configureLayoutFn` is a factory function that adds the new layout component to the `ReplaceableComponentsService`. The `APP_INITIALIZER` provider runs this function when the application starts.
note: (don't forget: you should add the CUSTOM_LAYOUT_PROVIDERS in the app.module.ts file)
#### Step 4: Define the Application's Dynamic Layouts
Finally, you need to define the application's dynamic layouts. This is a map where the keys are the layout keys and the values are the layout components.
You can add the new layout to the existing layouts like this:
```javascript
export const myDynamicLayouts = new Map([...DEFAULT_DYNAMIC_LAYOUTS, [eCustomLayout.key, eCustomLayout.component]]);
```
#### Step 5: Pass the Dynamic Layouts to the CoreModule
The final step is to pass the dynamic layouts to the `provideAbpCore` using the `withOptions` method. This method allows you to configure the module with a static method.
Here's how you can do it:
```ts
@NgModule({
providers: [
// ...
provideAbpCore(
withOptions({
dynamicLayouts: myDynamicLayouts,
environment,
registerLocaleFn: registerLocale(),
}),
),
],
})
export class AppModule {}
```
In this code, `myDynamicLayouts` is the map of dynamic layouts you defined earlier. We pass this map to the `provideAbpCore` using the `withOptions` method.
Now that you have defined the new layout, you can use it in the router definition. You do this by adding a new route that uses the new layout.
Here's how you can do it:
```javascript
// route.provider.ts
import { eCustomLayout } from './custom-layout/custom-layout.provider';
import { RoutesService, eLayoutType } from '@abp/ng.core';
import { APP_INITIALIZER } from '@angular/core';
export const APP_ROUTE_PROVIDER = [
{ provide: APP_INITIALIZER, useFactory: configureRoutes, deps: [RoutesService], multi: true },
];
function configureRoutes(routes: RoutesService) {
return () => {
routes.add([
{
path: '/',
name: '::Menu:Home',
iconClass: 'fas fa-home',
order: 1,
layout: eLayoutType.application,
},
{
path: '/dashboard',
name: '::Menu:Dashboard',
iconClass: 'fas fa-chart-line',
order: 2,
layout: eCustomLayout.key as eLayoutType,
requiredPolicy: 'MyProjectName.Dashboard.Host || MyProjectName.Dashboard.Tenant',
},
]);
};
}
```
#### How to Replace LogoComponent

Run the following command in `angular` folder to create a new component called `LogoComponent`.
```bash
yarn ng generate component logo --inlineTemplate --inlineStyle
```
Open the generated `logo.component.ts` in `src/app/logo` folder and replace its content with the following:
```js
import { Component } from "@angular/core";
@Component({
selector: "app-logo",
template: `
`,
})
export class LogoComponent {}
```
Open `app.component.ts` in `src/app` folder and modify it as shown below:
```js
import { ..., ReplaceableComponentsService } from '@abp/ng.core'; // imported ReplaceableComponentsService
import { LogoComponent } from './logo/logo.component'; // imported LogoComponent
import { eThemeBasicComponents } from '@abp/ng.theme.basic'; // imported eThemeBasicComponents
//...
@Component(/* component metadata */)
export class AppComponent implements OnInit {
constructor(..., private replaceableComponents: ReplaceableComponentsService) {} // injected ReplaceableComponentsService
ngOnInit() {
//...
this.replaceableComponents.add({
component: LogoComponent,
key: eThemeBasicComponents.Logo,
});
}
}
```
The final UI looks like below:

#### How to Replace RoutesComponent

Run the following command in `angular` folder to create a new component called `RoutesComponent`.
```bash
yarn ng generate component routes
```
Open the generated `routes.component.ts` in `src/app/routes` folder and replace its content with the following:
```js
import { Component, HostBinding } from "@angular/core";
@Component({
selector: "app-routes",
templateUrl: "routes.component.html",
})
export class RoutesComponent {
@HostBinding("class.mx-auto")
marginAuto = true;
get smallScreen() {
return window.innerWidth < 992;
}
}
```
Import the `SharedModule` to the `imports` array of `AppModule`:
```js
// app.module.ts
import { SharedModule } from './shared/shared.module';
@NgModule({
imports: [
//...
SharedModule
]
)}
```
Open the generated `routes.component.html` in `src/app/routes` folder and replace its content with the following:
```html