SPFx with Angular, Full tutorial

 White you can use the pnp-generator, I really wanted to created this kind of solution all by myself, since I also wanted to implement it with SP-2019, with SFPx 1.4.x


Part 1: Setup

I started with a clean machine, installed LTS node 14.17.0, and installed latest gulp, yo, sp-generator for yo, and angular-cli

command:

npm install gulp yo @microsoft/generator-sharepoint --global

results:

+ gulp@4.0.2

+ yo@4.2.0

+ @microsoft/generator-sharepoint@1.12.1

command:

npm install -g @angular/cli

results:

+ @angular/cli@12.0.2

*NOTE - To the time of writing, I had an error

generating browser application bundles

so I downgraded to angular 10.x, and re-create the project

npm uninstall -g @angular/cli

npm cache clean --force

npm install -g @angular/cli@10.2.0


And so our journey begins!

Create new Ng project

ng new ng-for-spfx-ex

Create new SPFx WebPart Project - just yo



Part 2: Test NG with SPFx

Within the angular.json  file lets change the output path, I've made 1 folder, within I created both projects, and named the SPFx one as "SPFx-with-NG", as well as the WebPart. Config outputPath to a new "ng files" folder will make it so ng build will create all new files there.

"outputPath""../SPFx-with-NG/src/webparts/spFxWithNg/ng files",

(Also to make is faster I changed .browserslistrc to support only last 1 Chrome version)


ANGULAR

Angular need to be changed from being an app, to being a Custom Element.

THEORY Explained (shortly):

When you create an angular app, its a JS code that goes and finds a tag named, usually, <app-root></app-root>, and from there its implementing all kind of things.

Therefor your <script> callings are after the tag calling in your HTML.

But with SPFx we use require ect. so its bootstrapping before the tag is rendered. 

[*NOTE - You could theoretically change the ngDoBootstrap in a way that will wait for it, but then using Angular Elements is much less work.

Another viable way (sometimes) is to add the scripts to a Document Library, and in the render call both the tag and all the scripts from their right place. I used to do that with AngularJS + SP13.]

Custom Elements were introduced in ES5/6, its an API to create your own elements tags, instead a DIV tag, make your own MY-CLOCK tag. 

Important for our case is that you "teach" the browser about your new tag, and he will render in accordingly, and he will watch the DOM for you, so you put the tag whenever you want, the browser compiles it according to instructions.


PRACTICE

In order to change the whole app from an app to an element we need to do a few changes:

Install @angular/elements - ng add @angular/elements

Then change the end or app.module.ts to:

  providers: [{provide: APP_BASE_HREFuseValue: '/'}],
  //bootstrap: [AppComponent]
  entryComponents: [AppComponent]
})
export class AppModule { 
  constructor(private injectorInjector) {}

  public ngDoBootstrap() {
    if (!customElements.get('app-any-name')) {
      const AppElement = createCustomElement(AppComponent, { injector: this.injector });
      customElements.define('app-any-name'AppElement);
    }
  }
}

Explained:

  • Adding provider to fill the missing <base href="/"> meta-tag
  • Tell angular no to try and Bootstrap i.e. running all its JS immediately
  • Tell angular that AppComponent is a root-component via entryComponents 
  • Ask angular to transform AppComponent to a Custom Element (createCustomElement)

SPFx

Calling our scripts

/****  ANGULAR  *****/
require('./ng files/runtime.js')
require('./ng files/polyfills.js')
require('./ng files/styles.js')
require('./ng files/vendor.js')
require('./ng files/main.js')

And rendering

this.domElement.innerHTML = `<app-any-name></app-any-name>`

DONE! you can try gulp serve


AUTOMATION

If you want to use the "save-compile-show in browser" functionality use ng build --watch on your Ng project, and gulp serve on the SPFx project

To use it on your SharePoint site use /_layouts/15/workbench.aspx. You will need to refresh the page.

To test it in your SharePoint page, instead the workbench.aspx, just add 

?loadSPFX=true&debugManifestsFile=https%3A%2F%2Flocalhost%3A4321%2Ftemp%2Fmanifests.js

Finally you can make it that gulp will serve inside your SharePoint page by changing inside /config/serve.json this line to this

  "initialPage""https://bresleveloper.sharepoint.com/sites/teamsiteexample/spfx-angular?loadSPFX=true&debugManifestsFile=https%3A%2F%2Flocalhost%3A4321%2Ftemp%2Fmanifests.js",


PageContext

I really like to have the PageContext whenever I develop side-thing to SPFx.

The trick I usually do is window['ctx'] = this.context.pageContext within the render function

But I want angular to know my ctx, so I clicked F12 on pageContext  and then again on PageContext  and that got me to a index-internal.d.ts file. I copied it to my angular models folder, deleted the import on top and deleted error refs or changed them to any 

Result:

export class AppComponent {
  title = 'Ng-For-SPFx';
  ctx:PageContext = window['ctx']
  absUrl = this.ctx.site.absoluteUrl
}


Thanks to Andrew Connell for Inspiration and guidance in his Angular SPFx Series

You can check in on my github




Would you like my help to create SPFx webparts with or without Angular? Contact us now!

Comments

  1. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Spfx With Angular, Full Tutorial >>>>> Download Now

      >>>>> Download Full

      Spfx With Angular, Full Tutorial >>>>> Download LINK

      >>>>> Download Now

      Spfx With Angular, Full Tutorial >>>>> Download Full

      >>>>> Download LINK 3w

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Spfx With Angular, Full Tutorial >>>>> Download Now

    >>>>> Download Full

    Spfx With Angular, Full Tutorial >>>>> Download LINK

    >>>>> Download Now

    Spfx With Angular, Full Tutorial >>>>> Download Full

    >>>>> Download LINK Td

    ReplyDelete

Post a Comment

Popular posts from this blog

OverTheWire[.com] Natas Walkthrough - JUST HINT, NO SPOILERS

Asp.Net Ending Response options, Response.End() vs CompleteRequest()

SOLVED The item could not be indexed successfully because the item failed in the indexing subsystem