How to use AngularJS in SharePoint Framework (SPFx)

In this post, I will show you how to use AngularJS in SPFx. I have divided the steps for better understanding.

Here are the steps:

1.       Create SPFx Project with No JavaScript Web Framework
2.       Add Dev Dependencies
3.       Remove some Dependencies
4.       Run “npm install”
5.       Modify “config.json”
6.       Create folder called “app” under “/src/webparts/ angularjsWebpart/” and Create following files in “app” folder
a.       Greetings.component.html
b.       Greeting.module.css
c.       Greetings.component.ts
d.       Greetings.service.ts (If required)
e.       app.module.ts
7.       Modify “<<your_webpart>>webpart.ts” file & add some code.
8.       Finally run your solution


Create SPFx Project with No JavaScript Web Framework

Remember you have to create project with No javascript web framework option.

Create a new project directory in your favorite location.
md angularjs-webpart

Go to the project directory.
cd angularjs-webpart

Create a new angularjs web part by running the Yeoman SharePoint Generator.
yo @microsoft/sharepoint

When prompted:
  • Accept the default angularjs-webpart as your solution name, and then select Enter.
  • Select SharePoint Online only (latest), and select Enter.
  • Select Use the current folder for where to place the files.
  • Select N to not allow the solution to be deployed to all sites immediately.
  • Select N on the question if solution contains unique permissions.
  • Select WebPart as the client-side component type to be created.


The next set of prompts ask for specific information about your web part:
  • Accept the default angularjs as your web part name, and then select Enter.
  • Accept the default angularjs description as your web part description, and then select Enter.
  • Accept the default No javascript web framework as the framework you would like to use, and then select Enter.


At this point, Yeoman installs the required dependencies and scaffolds the solution files along with the angularjs web part. This might take a few minutes.

When the scaffold is complete, you should see the following message indicating a successful scaffold.

Add Dev Dependencies

After creation of project, open this project in Visual Studio Code. Now open “package.json” and add following line of code in “devDependencies” section :

    "@types/angular""^1.6.57",
    "@types/jquery""^3.3.31",
    "@types/es6-promise""0.0.33",
    "@types/webpack-env""1.13.1",
    "sp-pnp-js""^3.0.10"

Here we are installing developer dependencies for AngularJS, Jquery & sp-pnp-js.

Remove some Dependencies

Remove following code from “dependencies” section:
    "@types/es6-promise""0.0.33",
    "@types/webpack-env""1.13.1"

Run “npm install”

Now we have to run npm install command to install dependencies in our project.

Modify “config.json”

Now navigate to “config” folder and open “config.json” & modify “externals” section with following values :

"externals": {
    "jquery""https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js",
    "angular": {
      "path""https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js",
      "globalName""angular"
    },
    "es-promise""https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.min.js",
    "fetch""https://cdnjs.cloudflare.com/ajax/libs/fetch/3.0.0/fetch.js",
    "sp-pnp-js":"https://cdnjs.cloudflare.com/ajax/libs/sp-pnp-js/3.0.10/pnp.min.js"
  },

Create folder called “app” under “/src/webparts/angularjsWebpart /” and Create following files in “app” folder

Greetings.component.html

<div class="demo" ng-cloak>
  <div class="container">
      <div class="row">
          <div class="col-lg-12 col-md-12 col-sm-12">
              <div class="email-signature">
                  <div class="signature-img">
                      <img ng-src="{{$ctrl.userImageUrl}}" alt="">
                  </div>
                  <div class="signature-details">
                      <h3 class="title">{{$ctrl.userName}}</h3>
                      <span class="post">{{$ctrl.userJobTitle}}</span>
                  </div>
                  <ul class="signature-content">
                      <li><span class="fas fa-map-marker-alt"></span> {{$ctrl.greetingMessage}}</li>
                      <li><span class="fas fa-envelope"></span> {{$ctrl.webSiteTitle}}</li>
                  </ul>
              </div>
          </div>
      </div>
  </div>
</div>



Greeting.module.css

:root {
  --color_0#000;
  --color_1#fff;
  --name#abb7c5;
  --shadowrgba(0000.5);
  --main_bglinear-gradient(to right#181623 13%#3c3b43 21%);
  --before_bglinear-gradient(to bottom#f9da41#fa771c);
  --after_bglinear-gradient(to bottom#a2eee1#1b819a);
  --main_bg_reslinear-gradient(to top#181623 13%#3c3b43 21%);
  --before_bg_reslinear-gradient(to right#f9da41#fa771c);
  --after_bg_reslinear-gradient(to right#a2eee1#1b819a);
}
.email-signature {
  backgroundvar(--main_bg);
  font-family"Roboto"sans-serif;
  padding20px 185px 20px 10px;
  box-shadow0 0 10px var(--shadow);
  positionrelative;
  text-aligncenter;
}
.email-signature:before,
.email-signature:after {
  content"";
  backgroundvar(--before_bg);
  height100%;
  width100px;
  positionabsolute;
  right0;
  top0;
}
.email-signature:after {
  backgroundvar(--after_bg);
  width20px;
  right110px;
}
.email-signature .signature-img {
  height140px;
  width140px;
  border7px solid var(--color_1);
  border-radius25px;
  overflowhidden;
  transformtranslateY(-50%);
  positionabsolute;
  right35px;
  top50%;
  z-index1;
}
.email-signature .signature-img img {
  width100%;
  heightauto;
}
.email-signature .signature-details {
  colorvar(--name);
  font-size15px;
  margin-bottom20px;
  text-aligncenter;
}
.email-signature .title {
  font-size22px;
  font-weight600;
  text-transformuppercase;
  letter-spacing1px;
  margin0;
  displayblock;
}
.email-signature .title span {
  font-weight400;
}
.email-signature .signature-content {
  colorvar(--color_1);
  font-size14px;
  line-height28px;
  padding0 0 0 20px;
  margin0;
  list-stylenone;
}
.email-signature .signature-content li span {
  margin-right6px;
}
.email-signature .icon {
  background-colorvar(--color_1);
  height100%;
  padding65px 30px;
  margin0;
  list-stylenone;
  positionabsolute;
  left0;
  top0;
}
.email-signature .icon li a {
  colorvar(--color_1);
  background-colorvar(--name);
  font-size16px;
  text-aligncenter;
  line-height25px;
  height25px;
  width25px;
  margin-bottom10px;
  displayblock;
  transitionall 0.3s ease 0s;
}
.email-signature .icon li a:hover {
  colorvar(--name);
  background-colorvar(--color_0);
  text-decorationnone;
  box-shadow0 0 10px var(--shadow);
}
@media screen and (max-width767px) {
  .email-signature {
    backgroundvar(--main_bg_res);
    text-aligncenter;
    padding175px 20px 70px 20px;
  }
  .email-signature .signature-img {
    transformtranslateY(0translateX(-50%);
    top20px;
    left50%;
  }
  .email-signature:before,
  .email-signature:after {
    backgroundvar(--before_bg_res);
    width100%;
    height70px;
    transformtranslateY(0);
    top0;
    left0;
  }
  .email-signature:after {
    backgroundvar(--after_bg_res);
    height20px;
    top85px;
  }
  .email-signature .signature-details {
    margin0 0 5px 0;
  }
  .email-signature .signature-content {
    padding0;
  }
  .email-signature .icon {
    width100%;
    heightauto;
    padding15px 0;
    topauto;
    bottom0;
  }
  .email-signature .icon li {
    displayinline-block;
  }
  .email-signature .icon li a {
    margin0 5px;
  }
}



Greetings.component.ts

import { GreetingService } from "./Greetings.service";

export class GreetingController {
  public userNamestring = "";
  public userJobTitlestring = "";
  public webSiteTitlestring = "";
  public welComeMessagestring = "";
  public userImageUrlstring = "";

  public greetingMessagestring = "";
  public prefixWelcomeMessagestring = "Welcome to ";

  public static $injectstring[] = ["GreetingService""$scope"];

  constructor(
    // tslint:disable-next-line: no-shadowed-variable
    private GreetingServiceGreetingService,
    private $scopeng.IScope
  ) {
    this.$scope.$on(
      "configurationChangedGreetingWebPart",
      (eventng.IAngularEventdataany=> {
        this.webSiteTitle = data.webTitle;
        this.userName = data.userDisplayName;
        this.getValues();
        console.log(this.userImageUrl);
        //this.$scope.$apply();
      }
    );
    this.getValues();
  }

  public getValues = () => {
    if (new Date().getHours() > 0 && new Date().getHours() < 12)
      this.greetingMessage = "Good Morning ";
    else if (new Date().getHours() >= 12 && new Date().getHours() <= 5)
      this.greetingMessage = "Good Afternoon ";
    else if (new Date().getHours() > 5this.greetingMessage = "Good Evening ";

    if (this.userName.length == 0this.userName = "Gaurav Goyal";

    if (this.userJobTitle.length == 0this.userJobTitle = "";

    if (this.webSiteTitle.length == 0)
      this.webSiteTitle = this.prefixWelcomeMessage + "Demo of SPFx Web Part";

    if (this.welComeMessage.length == 0)
      this.welComeMessage = this.greetingMessage + this.userName;

    // if (this.userImageUrl.length == 0)
    //   this.userImageUrl ="";

    this.getCurrentUserInformation();

  }

  public getCurrentUserInformation = () => {
    this.GreetingService.getCurrentUserInformation().then(ig => {
      this.webSiteTitle = this.prefixWelcomeMessage + this.webSiteTitle;
      this.userImageUrl = ig.userImageUrl;
      //this.userName = this.userName;
      this.userJobTitle = ig.userJobTitle;
      this.$scope.$apply();
    });
  }
}

export let GreetingComponent = {
  selector: "greetingComponent",
  template: require("./Greetings.component.html").toString(),
  bindings: {},
  controller: GreetingController,
  styles:require("./Greeting.module.css").toString()
};



Greetings.service.ts (If required)

import { IGreeting } from "./IGreeting";
//import * as angular from 'angular';
import * as $pnp from "sp-pnp-js";

export class GreetingService {
  constructor() {}

  public getCurrentUserInformation = (): Promise<IGreeting=> {
    let promise = new Promise<IGreeting>((resolvereject=> {
      let igIGreeting = {
        userImageUrl: "",
        userJobTitle: "",
        userName: "",
        webSiteTitle: ""
      };

      $pnp.sp.profiles.myProperties.get().then(
        data => {
          data.UserProfileProperties.forEach(property => {
            if (property.Key == "Title") {
                ig.userJobTitle = property.Value;
            }

            if (property.Key == "PictureURL") {
              if(property.Value !==''){
                ig.userImageUrl = property.Value;}
              else{
                ig.userImageUrl = "https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png";
              }
              ig.userImageUrl = ig.userImageUrl.replace("MThumb""LThumb");
            }
          });
          resolve(ig);
        },
        error => {
          reject(error);
        }
      );
    });
    return promise;
  }
}



app.module.ts

import * as angular from 'angular';
import {GreetingComponentGreetingControllerfrom './Greetings.component';
import { GreetingService } from './Greetings.service';

const greetingAppangular.IModule = angular.module('greeting-webpart-app', []);

greetingApp
  .service("GreetingService"GreetingService);

greetingApp
   .controller('GreetingController'GreetingController);

  greetingApp
  .component(GreetingComponent.selectorGreetingComponent);



Modify “<<your_webpart>>webpart.ts” file & add some code.


At the top of the file, add 2 highlighted lines.

import { Version } from '@microsoft/sp-core-library';
import {
  IPropertyPaneConfiguration,
  PropertyPaneTextField
from '@microsoft/sp-property-pane';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import { escape } from '@microsoft/sp-lodash-subset';

import styles from './GreetingsWebpartWebPart.module.scss';
import * as strings from 'GreetingsWebpartWebPartStrings';

export interface IGreetingsWebpartWebPartProps {
  descriptionstring;
}

import * as angular from "angular";
import "./app/app.module";



Replace the render function:

public render(): void {

    if (this.renderedOnce === false) {
      this.domElement.innerHTML = `<greeting-component></greeting-component>`;
      this.$injector = angular.bootstrap(this.domElement, ["greeting-webpart-app"]);
    }

    let obj1={
      //webTitle, userDisplayName
      currentUserId: this.context.pageContext.legacyPageContext['userId'],
      webAbsoluteUrl: this.context.pageContext.legacyPageContext['webAbsoluteUrl'],
      webTitle: this.context.pageContext.legacyPageContext['webTitle'],
      userDisplayName: this.context.pageContext.legacyPageContext['userDisplayName'],
      tempData: this.properties.description
    };

    this.$injector.get("$rootScope").$broadcast("configurationChangedGreetingWebPart"obj1);
  }



Finally run your solution


gulp serve –nobrowser
                run your sharepoint workbench
                                https://<<TenantName>>.sharepoint.com/_layouts/15/workbench.aspx
                                Add webpart & see the result

My sample code is part of  PnP community - SPFx Dev webpart sample.  Click here to download the code.

Comments

Popular Posts

SharePoint Interview Questions and Answers

Download Infopath Form Templates

How to get current logged user information using JavaScript ?

Steps to set Form based authentication (FBA) for SharePoint 2010

SharePoint Interview Questions and Answers II

Get List Items - JavaScript

Change Language for current user with JSOM in SharePoint Online

Cross Site List Rollup Web Part for SharePoint 2010

Hide Recently Modified Items

SharePoint 2010 CSS Chart