April 11, 2020
Estimated Post Reading Time ~

Part 1 - Angular 2 with AEM – Introduction, Challenges, Installation and Prerequisite

I am writing about AEM after long time and there is a reason for that :-) I was learning something else interesting and that interesting thing is frontend technologies. So far in my professional career, I have spent most of my time designing and developing server-side applications mainly using Java technology stack (Spring, ORM, JMS and what not) with basic UI development using JSP/JSF, HTML, Velocity, Sightly, jQuery, ExtJS, etc. Also, in the last few years, I have delivered many applications which are combination of AEM, other CMS, and Java backend but, I felt that still there is something missing and that missing piece is an end to end knowledge of frontend development. 

So that’s what I was focusing on frontend development in the recent past. I thought it is a good time to combine frontend development knowledge with AEM and come up with something interesting that might help my friends out there.

In this multi-series post (and tutorial incoming parts of this series), I’ll show you how you can use Angular 2 in AEM. There are lot of posts already out there then, why do I need a separate post on this topic? I see a lot of articles on web that are trying to address how to use AEM and Angular2 together but, most of them are either incomplete or just shows how to create clientlib for Angular2 dependencies or how to create a plain vanilla Angular 2 component (not AEM component) that authors cannot drag and drop (like regular AEM components). 

For almost last 2 years I spent a good amount of time learning front end technologies like (Angular 1.x, Angular2, ES6, Typescript, Ionic 1 & 2, Native Script, etc.) along with Node.js and I felt this is the time when I know both worlds; AEM and Angular 2 quite well and I can attempt to develop something using AEM and Angular 2 by harnessing the power of both. You’ll have to be focused and patient while going through this multi-series post.

For those who don’t know what is AEM and Angular 2, I’ll be with quick non-technical introduction.

What is AEM?
Adobe Experience Manager (AEM), is a comprehensive content management platform solution for building websites, mobile apps and forms - making it easy to manage your marketing content and assets. AEM empowers business users and non-technical staff to create and manage content as per business needs.

What is Angular 2?
Angular is a platform that makes it easy to build applications with the web. Angular combines declarative templates, dependency injection, end to end tooling, and integrated best practices to solve development challenges. Angular 2 comes with almost everything you need to build a complicated frontend web or mobile apps, from powerful templates to fast rendering, data management, HTTP services, form handling, and so much more. Angular 2 is a component centric framework that promotes reusable component development. In Angular 2, “everything is a component.” Components are the main way we build and specify elements and logic on the page, through both custom elements and attributes that add functionality to our existing components.

Since Angular2 is primarily based on Typescript, therefore, we get all the benefits of a typed language. Angular 2 and TypeScript are bringing true object-oriented web development to the mainstream, in a syntax that is strikingly close to Java 8.

Why use Angular 2 in AEM?
For any delivery channel (web, mobile etc.) content is no doubt key but, at the same time, it is also very important how that content is presented to users (this is where user experience comes). No matter how good content is if it is not available to users in the format that is easy to read, understand, in right context with good performance then it will lose its value. This is where Angular 2 helps to design more robust and performant user experience using modern technology and standards.

Challenges that I faced while integrating Angular 2 with AEM
1. AEM and Angular 2 components are different: Angular 2 is modular in nature, what that means is there are a number of smaller modules that you can choose to mix and match based on what is required in your project. When you are developing Angular 2 application outside of AEM this is not a big challenge in terms of building and shipping an Angular 2 application out of the door because there are many build tools (e.g. Angular 2 CLI) are available to take care of managing these smaller angular modules and dependencies. 

But, when we are in AEM, components are just building blocks and content authors can drag-drop these components anywhere and as many times as they need so, reusability is key i.e. authors should be able to use Angular 2 components in the same way as regular AEM component. So this means build tools that are available today for Angular 2 application can’t help because those tools need to know upfront where components have been used and then these tools compile applications but, in AEM this is different (as we discussed above).

To address this problem we need to write our custom build script using gulp (we can use grunt as well) and Maven.

2. Angular 2 application root component bootstrapping and AEM component model: typically an Angular 2 application has one root element where the main application is bootstrapped. All other Angular 2 components have to be child of this root element else Angular will not detect them. 

For example:


In the above diagram is the application root component and everything else (including components imported from other Angular 2 modules) needs to be rendered inside. This is a big challenge because we want parsys to be available inside an Angular 2 component, and we should also be able to drag-drop component in that parsys...this sounds complex huh!!! Yes, it is a little complicated and took some time for me as well to figure out how this can be achieved.

To overcome this, we need to use some internal Angular 2’s core classes like “ComponentFactoryResolver” and “ApplicationRef” to change the way Angular 2 application is bootstrapped in normal applications and loading Angular 2 components dynamically at runtime.

3. Angular 2 component & authoring: one of the key capability of AEM component is content authors have full control over text/labels, they can change text without IT team’s involvement but, on the other hand, Angular 2 component needs to know the text values (labels, etc.) up front and if there are any changes then we need to rebuild application or at the very best we can externalised labels into translation bundle files so that we don’t need to change code but, still this is not aligned with how component authoring works in AEM.

To overcome this, we need to use Angular 2 features like @Input so that we can read JCR properties and pass it to Angular 2 component’s template for rendering.

4. Angular 2 component’s view/template: Let’s look at a simple Angular 2 component

import {Component, OnInit} from "@angular/core";

@Component({
selector: "app",
templateUrl: "/apps/ngaem/content/ng-app/app.html"
})
export class AppComponent implements OnInit {
ngOnInit() {
console.log("Application component initialized ...");
}
}


As you can see, the Angular 2 component’s actual view is in some external template “app.html”. If we want to treat an Angular 2 component as AEM component then app.html, in this case, will become sightly template (or JSP, JSP is not recommended to use because we want to leverage HTML5 features when using Angular 2). If you notice, the template is directly fetched from /apps folder (which is a secured folder on the server) and we don’t want users to have direct access to anything that resides in /apps folder in publish environment.

To overcome this, we need to write a custom Sling servlet that can serve view/template to angular component. This servlet will be responsible for reading the view file (e.g. app.html) from the apps folder and send text/html response back to the caller (in this case Angular 2 component). Here is a quick example of how the view will be referenced from the Angular 2 component:

@Component({
selector: "app",
templateUrl: "/bin/ngtemplate?path=/apps/ngaem/content/ng-app/app.html"
})

/bin/ngtemplate is Sling servlet that serves the content of app.html

5. Preview of Angular 2 component in author environment: a component can be dropped by an author on a page (when they are in edit mode) and they can preview how actual pages looks like (in preview mode). When an Angular 2 component is dropped on a page it needs to be intercepted by Angular 2 library and bootstrap or attach it to DOM. Even though the Angular 2 library is available on the page but, for some weird reason Angular was not able to bootstrap/attach component’s view when I was in EDIT and PREVIEW mode. For Angular component to work I have to use wcmmode=disabled in the query string.

Image: Angular 2 TextArea Component in EDIT/PREVIEW mode


Image: Angular 2 TextAreaComponent in DISABLED mode

To overcome this I used “wcmmode”, and if wcmmode is either EDIT or PREVIEW directly render the .html file of component and in this case data will not be bound i.e. {{some_angular_variable}} will be rendered rather than the actual value. Here is a quick code snippet that shows how I am loading template in EDIT/PREVIEW mode v/s when wcmmode is DISABLED (need to pass query parameter in URL ?wcmmode=disabled):

<div data-sly-use.logic="logic.js">
<div data-sly-test="${wcmmode.edit || wcmmode.preview}">
<!-- Render HTML file in EDIT and PREVIEW mode-->
<section data-sly-include="text.html"></section>
</div>
<div data-sly-test="${!wcmmode.edit && !wcmmode.preview}">
<!-- Render by Angular 2 component in wcmmode=DISABLED mode-->
<text-area text="${properties.text}"></text-area>
</div>
</div>


6. Speed of development and validating Angular functionality and AEM functionality independently: developer is more productive when they can make code changes and quickly verify it without redeployment. We feel more confident when we have suite if unit tests to verify our code so that undesirable code changes can be caught during development. When we want to use Angular 2 in AEM we have to deal with 2 different approaches for developing and testing applications because Angular 2 development itself is quite different than AEM and Angular 2 is mostly used without AEM. Challenge comes when we want to use both together. Both Angular 2 and AEM components should be unit testable (Angular 2 testing using Mocha, Chai, Sinon, etc.) AEM with Junit, Mockito, etc. and developer should be able to test their code quickly without redeployment.

To do this, I have leveraged power of frontend build tools Gulp to create two separate Angular 2 build tasks:
  • One for AEM which compiles Typescript files, updates template path in Angular 2 component with Sling servlet context path, copy resources that are needed for creating AEM CRX package
  • The second task for building pure Angular 2 project that can be built and tested outside of AEM using a local lite-server https://github.com/johnpapa/lite-server
7. Importing Angular 2 dependencies and loading them on AEM template: Angular 2 primarily recommends using Typescript for Angular 2 application development although you can use Javascript as well. If you are from Java background you’ll feel like you are writing Java code when you use Typescript and you get all most all the benefit of a typed language. When you want to use Angular 2 in AEM you need to bring in all dependencies of Angular (e.g. @angular/core, @angular/common, @angular/compiler, @angular/http, etc.) in AEM and make them available on your pages via a template. These dependencies are modular and can be loaded on demand (i.e. when it is really needed by your Angular 2 component, services/providers). For example, you are writing a simple Angular 2 Text component that does not talk to any REST service then you really don’t need @angular/http module loaded on your page. In AEM there are 2 ways you can achieve this one using clientlib (define inter-dependencies between various modules) or you can use frontend bundle packaging and loading tools like Webpack or Systemjs.

In this series of tutorials, I am going to use Systemjs. Systemjs allows you to load JS dependencies from AEM.

I just wanted to give you an overview of some of the challenges that I faced while integrating Angular 2 with AEM so that you can follow the rest of the parts in this series with a better context and background. I’ll cover each of these challenges in more other parts of this series so that you can get more knowledge about these topics.

What you need to know to follow the remaining parts of this series?
If you know Java, AEM, and Angular2 you can easily follow this series of tutorial but, if you want to do some hands-on along with going through this tutorial then I’ll recommend you to get a fair understanding of following:
  1. Good understanding of Java and AEM (components, templates, Sling Servlet, etc.)
  2. Good understanding of JavaScript and Typescript (https://www.typescriptlang.org)
  3. Good understanding of Angular2 (https://angular.io/docs)
  4. Good understanding of Systems (https://github.com/systemjs/systemjs)
  5. Basic understanding of front-end build tool (gulp: http://gulpjs.com) and Maven build tool (https://maven.apache.org)
Tools and Installation
Also, to build and run the project you’ll need to install:
  1. Node.js - https://nodejs.org/en
  2. TypeScript - https://www.npmjs.com/package/typescript
  3. Gulp - http://gulpjs.com
  4. Maven - https://maven.apache.org
  5. Java /JDK 1.7 or later - https://www.java.com/en/download
  6. Eclipse - http://www.eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/neon
  7. Eclipse AEM plugin - https://eclipse.adobe.com/aem/dev-tools
  8. AEM - If you don’t have AEM already then getting it might be tricky because it is licensed. You can look at this thread https://forums.adobe.com/thread/2322257 and another link https://helpx.adobe.com/support.html#/top_products
I hope you have got some context now and will enjoy the next parts in this series. Be ready with the installation of tools that I have listed above. Stay tuned for a github repository with sample code and links for the next parts in this series.

Github Project/Source Code: https://github.com/suryakand/aem-angular2

Source: http://suryakand-shinde.blogspot.com/2017/06/part-1-angular-2-with-aem-introduction.html


By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.