Angular 6+ inside Adobe Experience Manager

Assets directory
cd front-end
ng serve

1. Exposing our component as a custom element

ng add @angular/elements
npm install @webcomponents/custom-elements --save
npm install document-register-element@1.8.1 --save

There is currently a bug in angular elements that it breaks if we try to use a higher version of document-register-element, but in the future, you should be able to use the latest versions.

constructor(private injector: Injector) {}ngDoBootstrap() {
const weatherElement = createCustomElement(
WeatherComponent,
{injector: this.injector }
);
customElements.define('weather-ng', <any>weatherElement);
}

2. Building and creating a clientlib

"build:elements": "ng build --prod --output-hashing none && node elements-build.js"
const fs = require('fs-extra');
const concat = require('concat');
(async function build() {
const files = [
'./dist/front-end/runtime.js',
'./dist/front-end/polyfills.js',
'./dist/front-end/scripts.js',
'./dist/front-end/main.js',
];
const rootDir = '../ui.apps/src/main/content/jcr_root/etc/designs/ngx';await fs.ensureDir(`${rootDir}/clientlib-site/js`);
await fs.ensureDir(`${rootDir}/clientlib-site/css`);
await concat(files, `${rootDir}/clientlib-site/js/ng-aem.js`);await fs.copyFile('./dist/front-end/styles.css', `${rootDir}/clientlib-site/css/ng-aem.css`);await fs.copy('./dist/front-end/etc/designs/ngx/assets/', `${rootDir}/assets`);await fs.copy('./dist/front-end/weathericons-regular-webfont.eot', `${rootDir}/clientlib-site/css/weathericons-regular-webfont.eot`);
await fs.copy('./dist/front-end/weathericons-regular-webfont.svg', `${rootDir}/clientlib-site/css/weathericons-regular-webfont.svg`);
await fs.copy('./dist/front-end/weathericons-regular-webfont.ttf', `${rootDir}/clientlib-site/css/weathericons-regular-webfont.ttf`);
await fs.copy('./dist/front-end/weathericons-regular-webfont.woff', `${rootDir}/clientlib-site/css/weathericons-regular-webfont.woff`);
await appendDataIfNotExists(`${rootDir}/clientlib-site/js.txt`, 'ng-aem.js');
await appendDataIfNotExists(`${rootDir}/clientlib-site/css.txt`, 'ng-aem.css');
console.log("Done with moving angular libs to AEM");})();async function appendDataIfNotExists(file, toAppend) {
const data = await fs.readFile(file, 'utf8');
if (!data.split('\n').find((val) => val === toAppend)) {
await fs.writeFile(file, data + '\n' + toAppend);
}
}
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.6</version>
<configuration>
<nodeVersion>v10.4.1</nodeVersion>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<phase>generate-resources</phase>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<phase>generate-resources</phase> <configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>npm run build custom elements</id>
<goals>
<goal>npm</goal>
</goals>
<phase>generate-resources</phase> <configuration>
<arguments>run build:elements</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

3. Creating the AEM component

@Model(adaptables=Resource.class)
public class WeatherModel {
@Inject
@Named("unitType")
@Default(values="")
private String unitType;
public String getUnitType() {
return unitType;
}
public void setUnitType(String unitType) {
this.unitType = unitType;
}
}
<unitType jcr:primaryType="nt:unstructured"       sling:resourceType="granite/ui/components/foundation/form/select"
fieldLabel="Link Color"
name="./unitType">
<items jcr:primaryType="nt:unstructured">
<default jcr:primaryType="nt:unstructured" text="Kelvin" value=""/>
<metric jcr:primaryType="nt:unstructured" text="Celcius" value="metric"/>
<imperial jcr:primaryType="nt:unstructured" text="Farenheit" value="imperial"/>
</items>
</unitType>
<div data-sly-test="${wcmmode.edit}">
<h3>Drag here the components you want to display in your weather component</h3>
<div data-sly-resource="${'content' @ resourceType='wcm/foundation/components/parsys'}"></div>
</div>
<weather-ng data-sly-test="${wcmmode.disabled}" data-sly-use.weather="com.did.core.models.WeatherModel" unit="${weather.unitType}">
<div data-sly-resource="${'content' @ resourceType='wcm/foundation/components/parsys'}"></div>
</weather-ng>
Author view
The view when wcmmode=disabled

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store