Skip to main content

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 from this blog

Export / Import from Excel file in SharePoint

SharePoint Web Part - Export or Import from Excel Here is the tool which will help you to import excel file into a list. This tool will not create any kind of list or column. It will help users to import their excel file in specific list. This tool also allows users to update existing records directly from excel file. I have develop the tool in SharePoint Framework. Currently this tool is for SharePoint Online version only. We are supporting following columns : Single line of text Multiple lines of text Number Yes/No Person or Group (Person + Group) Person or Group (Person + Group) (Allow multiple selections) Date and Time Choice Choice (Allow multiple selections) Hyperlink or Picture Currency Managed Metadata Managed Metadata (Allow multiple values) Lookup Lookup (Allow multiple values) Installation of App :- 1. Click here to download the sps-import-from-excel.sppkg . 2. Visit the Microsoft 365 SharePoint Admin Center 3. Go to Apps -> App Catalog. If you don't have ap

Deploy SPFx production solution files in specific folder with in container on Azure CDN

Hi, When we creates SPFx solution and deploying the build files on Azure CDN, it deploys all the files in a container which you mentioned in "deploy-azure-storage.json" file. This is bit messy to see. Because you can deploy multiple solution on the same container. But what if you want to manage solutions by Solutions or By versions. Here is the way. I will show you how to deploy SPFx production deployment files in a specific folder in the Container on Azure CDN. First you have to deploy some gulp task packages in dev-dependencies npm install gulp-util gulp-deploy-azure-cdn --save-dev Now you need to make following changes in the "gulpfile.js" file : const deployCdn = require('gulp-deploy-azure-cdn'); const gutil = require('gulp-util'); gulp.task('deploy-azure-storage-folder', function () {   return gulp.src('temp/deploy/**/*', {}).pipe(deployCdn({       containerName: '<<Your Container Name>>', // Container

Error while compiling spfx project - Error - typescript - node_modules/@fluentui/react-focus/node_modules

 Some when you create new project or upgrade existing project, developer get issues related to fluent ui packages i.e. : Error - typescript - node_modules/@fluentui/react-focus/node_modules/@uifabric/merge-styles/lib/DeepPartial.d.ts(4,26): error TS1005: ';' expected. Error - typescript - node_modules/@fluentui/react-focus/node_modules/@uifabric/merge-styles/lib/DeepPartial.d.ts(4,41): error TS1005: ')' expected. Error - typescript - node_modules/@fluentui/react-focus/node_modules/@uifabric/merge-styles/lib/DeepPartial.d.ts(4,42): error TS1005: ';' expected. Error - typescript - node_modules/@fluentui/react-focus/node_modules/@uifabric/merge-styles/lib/DeepPartial.d.ts(4,72): error TS1005: ';' expected. Error - typescript - node_modules/@fluentui/react-focus/node_modules/@uifabric/merge-styles/lib/DeepPartial.d.ts(4,107): error TS1005: '(' expected. Error - typescript - node_modules/@fluentui/react-focus/node_modules/@uifabric/merge-styles/lib/De