SPFx Webpart With Angular Elements

Introduction

As developers, we know SPFx and Angular both are the strongest frameworks. Recently PnP generator released version 1.14.0 with Angular 9 support. So, in this article, we will see the step-by-step implementation of SPFx web part integration with Angular elements.

What are Angular Elements?

Angular Elements is one of the best features released in Angular 6. It allows us to create Web Components (Custom Elements) using Angular. Angular elements are ordinary Angular components packaged as custom elements, a web standard for defining new HTML elements in a framework-agnostic way. This approach lets us develop reusable components in a way that’s familiar to us, and yet, embed these in every kind of website (vanilla JavaScript, React, Vue, WordPress, etc. ).

Prerequisites And Environment Setup

To develop the SPFx webpart with Angular Elements, we need Angular CLI and PnP Generator SPFx.

  • Angular CLI is a command-line interface for Angular. This gives various commands to scaffold projects and generate components, services, modules, and many more things.
  • PnP/generator-SPFx provides improved governance for SharePoint Framework projects. it extends the capabilities for ReactJS, and Knockout projects and supports additional frameworks, such as HandlebarsJS, Aurelia, VueJS, and Angular Elements.

Now we will install both packages globally using the below command.

npm install -g @angular/cli @pnp/generator-spfx

Let's start the development step by step.

Development

  • Open a command prompt
  • Move to the path where you want to create a project
  • Create a project directory using.
    md directory-name

Move to the above-created folder using

cd directory-name

Now execute the below command to create a solution

yo @pnp/spfx

It will ask some questions below

Project Setup

These commands will generate separate folders for angular elements and SPFx web part with the -spfx suffix.

After successful installation, an open project in VS Code executes the below command

code.

Successful installation

Demo Application

In this demo, we will get SharePoint list records and display them in webpart so let's start step-by-step implementation.

Install Bootstrap (for some designing purpose) in the Angular project executing the below command.

npm install bootstrap

Set the bootstrap path in the angular.json file as below.

"architect": {
  "build": {
    "styles": [
      "node_modules/bootstrap/dist/css/bootstrap.min.css",
      "src/styles.scss"
    ]
  }
}
  • Now we will create a service(to perform backend API calls)and model in the Angular project. For more details refer to this article.
  • Our Angular project structure now looks like this after creating models and services:
    Angular project

Now we will update the required files.

todo.model.ts

export interface ToDo {
  Id?: number;
  Title: string;
}

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Injector } from '@angular/core';
import { createCustomElement } from '@angular/elements';
import { SpFxAngular9WebPartComponent } from './sp-fx-angular9-web-part/sp-fx-angular9-web-part.component';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
  declarations: [
    SpFxAngular9WebPartComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [],
  entryComponents: [SpFxAngular9WebPartComponent]
})
export class AppModule {
  constructor(private injector: Injector) {}
  ngDoBootstrap() {
    const el = createCustomElement(SpFxAngular9WebPartComponent, { injector: this.injector });
    customElements.define('app-sp-fx-angular9-web-part', el);
  }
}

app.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { ListItems } from '../models/listItems.model';
import { map, tap, catchError } from 'rxjs/operators';
@Injectable({
  providedIn: 'root'
})
export class AppService {
  private BASE_URL = 'https://vtsp.sharepoint.com/';
  constructor(private httpClient: HttpClient) {}
  setAPIUrl(url: string) {
    this.BASE_URL = url || this.BASE_URL;
  }
  getListItems() {
    return this.httpClient
      .get<any>(`${this.BASE_URL}/_api/web/lists/getbytitle('React')/items?$select=Id,Title`)
      .pipe(map(response => response.value as ListItems[]))
      .toPromise();
  }
}

[WebpartName].component.ts

import { Component, Input, OnInit, ViewEncapsulation, Output, EventEmitter, OnDestroy } from '@angular/core';
import { ListItems } from '../models/listItems.model';
import { AppService } from '../services/app.service';
@Component({
  selector: 'app-sp-fx-angular9-web-part',
  templateUrl: './sp-fx-angular9-web-part.component.html',
  styleUrls: ['./sp-fx-angular9-web-part.component.scss'],
  encapsulation: ViewEncapsulation.Emulated
})
export class SpFxAngular9WebPartComponent implements OnInit {
  @Input()
  public set siteurl(url: string) {
    this.appService.setAPIUrl(url);
  }
  listItems: ListItems[];
  constructor(private appService: AppService) {}
  ngOnInit() {
    this.appService.getListItems().then(listItems => this.listItems = listItems);
  }
}

[WebpartName].component.html

<div class="col-md-8">
  <div class="card">
    <div class="card-body">
      <h3>List Items</h3>
      <table class="table">
        <thead>
          <tr>
            <th>Id</th>
            <th>Title</th>
          </tr>
        </thead>
        <tbody>
          <tr *ngFor="let listItem of listItems">
            <td scope="row">{{ listItem.Id }}</td>
            <td scope="row">{{ listItem.Title }}</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</div>

Bundle Angular elements

To use angular elements in the SPFx webpart we need to bundle it in a js file so we will execute the below command.

npm run bundle

This command generates Angular application bundles and styles.css and after that combines all the JS files into a bundle.js file.

Using SPFx Webpart With Angular Elements

Now we will import the styles.css file in our spfx webpartafter bundle.js statement in our webpart.ts file as below.

require('../../../node_modules/angular-elements/dist/AngularElements/styles.css');

and then we will update the render method.

Here <app-sp-fx-angular9-web-part> is the custom element, which we have created with Angular. We will add this custom element tag in DOM to render the Angular component in the web part.

public render(): void {
  const siteUrl = this.context.pageContext.web.absoluteUrl;
  this.domElement.innerHTML = `<app-sp-fx-angular9-web-part siteUrl="${siteUrl}"></app-sp-fx-angular9-web-part>`;
}

Now we will test it on a local server so for this we will bundle the Angular project and then run the spfx web part as below.

How to run SPFx webpart

  • Our application will serve on SharePoint-SiteURL + /_layouts/15/workbench.aspx page.
  • After this is successfully served on localhost we will deploy it in our SharePoint site using gulp bundle --ship and gulp package-solution --ship commands.

Output

List item

Find the complete source code here.

Summary

In this article, we have seen how to integrate the SPFx web part with Angular elements with prerequisites, environment setup, development, deployment, and demo application.

I hope this helps.

Sharing is caring!!!