Hi @harpreetsi5,
1. Angular Components Are Not Rendering on Pages
Ensure Angular is properly bootstrapped
In main.ts, make sure this exists:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
Use the Angular app selector in your HTL
In your AEM component HTL file (.html😞
<div class="my-angular-wrapper">
<app-root></app-root>
</div>
Make sure this selector matches what is defined in your AppComponent:
@Component({
selector: 'app-root',
...
})
Include Angular JS/CSS clientlibs in your AEM template
In the AEM page template HTL (e.g., structure/page.html😞
<cq:includeClientLib categories="yourproject.angular" />
Replace yourproject.angular with the category defined in your clientlibs-angular/.content.xml.
2. Component Mapping Doesn’t Work
Expose sling:resourceType in the model JSON
In your Sling Model (Java):
@ValueMapValue
@Optional
private String slingResourceType;
public String getSlingResourceType() {
return slingResourceType;
}
In the model exporter (using @Exporter), make sure the sling:resourceType is included in the output.
Map AEM components to Angular components
In Angular (component-mapping.ts😞
import { HeroComponent } from './components/hero/hero.component';
import { TeaserComponent } from './components/teaser/teaser.component';
export const COMPONENT_MAPPING: any = {
'myproject/components/content/hero': HeroComponent,
'myproject/components/content/teaser': TeaserComponent
};
Use a dynamic component loader
In your container Angular component (e.g., DynamicContainerComponent😞
import { Component, ComponentFactoryResolver, Input, ViewChild, ViewContainerRef } from '@angular/core';
import { COMPONENT_MAPPING } from './component-mapping';
@Component({
selector: 'dynamic-container',
template: `<ng-container #container></ng-container>`
})
export class DynamicContainerComponent {
@Input() componentType: string;
@ViewChild('container', { read: ViewContainerRef, static: true }) container: ViewContainerRef;
constructor(private resolver: ComponentFactoryResolver) {}
ngOnInit() {
const component = COMPONENT_MAPPING[this.componentType];
if (component) {
const factory = this.resolver.resolveComponentFactory(component);
this.container.createComponent(factory);
}
}
}
Then use this like:
<dynamic-container [componentType]="model['sling:resourceType']"></dynamic-container>
3. clientlibs-angular/js.txt is Empty
Ensure Angular output files go to the expected path
In angular.json:
"outputPath": "dist/angular-app"
Copy Angular output to AEM clientlibs-angular manually or via script
You can use a postbuild script in package.json:
"scripts": {
"build": "ng build",
"postbuild": "node scripts/copy-angular-assets.js"
}
scripts/copy-angular-assets.js:
const fs = require('fs');
const path = require('path');
const sourceDir = path.resolve(__dirname, '../dist/angular-app');
const targetDir = path.resolve(__dirname, '../../ui.apps/src/main/content/jcr_root/apps/yourproject/clientlibs/clientlibs-angular');
const jsFiles = fs.readdirSync(sourceDir).filter(f => f.endsWith('.js'));
const jsTxtContent = jsFiles.join('\n');
jsFiles.forEach(file => {
fs.copyFileSync(path.join(sourceDir, file), path.join(targetDir, file));
});
fs.writeFileSync(path.join(targetDir, 'js.txt'), jsTxtContent);
console.log('Copied JS files and updated js.txt');
Check that your .content.xml defines the clientlib correctly
clientlibs-angular/.content.xml:
<jcr:root
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="cq:ClientLibraryFolder"
categories="[yourproject.angular]"
dependencies="[yourproject.base]"
allowProxy="true"/>
Best Practices
Use Angular Elements (optional but helpful)
To avoid bootstrapping issues, wrap your Angular components as Web Components.
import { createCustomElement } from '@angular/elements';
const el = createCustomElement(MyComponent, { injector });
customElements.define('my-component', el);
Then you can use <my-component> directly in AEM HTL without worrying about Angular bootstrapping logic.
Hope that helps!