TutorialsEngineering

Using Weavy in Angular ASP.NET Core

May 25, 2021

Note: this tutorial was written for Weavy v8, which uses a different codebase than the current version of Weavy.

This will guide you through how to set up Weavy in a basic Angular ASP.NET Core app based on the samples from docs.microsoft.com. It will create a component for Weavy apps and a service for the Weavy client instance. It requires Weavy v8.2. The full demo is also available at GitHub.

Weavy Angular Core Demo at GitHub

angular+core+weavy2-1

Install dotnet

You will need at least ASP.NET Core 2.1 installed.

This demo can also be done using the GUI in Visual Studio instead of using dotnet CLI.

Follow the instuctions for your platform at dotnet.microsoft.com/learn/aspnet/hello-world-tutorial/intro.

To verify that it's working, simply type dotnet in your console.

Install Angular

Install Angular CLI globally. See angular.io/cli. The version of CLI you have will define which Angular version you will have in your project.

npm install @angular/cli -g

To install older versions or downgrade your CLI use the tag @vX-lts, where X is the version, or use @latest. See npmjs.com/package/@angular/cli

npm install @angular/cli@v7-lts -g

Create a dotnet angular app

This will create a basic ASP.NET Core app based on an Angular template, complete with routing and sample pages. If you already have an ASP.NET Core app with Angular, you can simply skip this step. The Angular app will be placed in a ClientApp folder. 

dotnet new angular -o WeavyAngularCore
cd WeavyAngularCore

Add Weavy client script

You can add the Weavy client in two ways; by including it normally as a script tag in html or as an included script in the build. The script will be available as a runtime-global library. See angular.io/guide/using-libraries for details on how to include the script in your build instead of adding it to HTML.

 

Getting started with Weavy Server SDK

 

Add script to HTML

Open ClientApp/src/index.html and add the script tags to the <head> section. For this demo we use our showcase -server, which you can use just to try it out. Then just replace the showcase.weavycloud.com with your own installation.

index.html

<head>
  <!-- ... -->
  <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
  <script src="https://showcase.weavycloud.com/javascript/weavy.js"></script>
</head>

Create a Weavy service

To create optimal performance, we will place the Weavy instance in a service. This way it will be reusable for each Weavy app component and we will avoid redundant initialization and calls to the server.

The simplest way to create a new service is to use the CLI. It will generate two files in ClientApp/src/app

ng generate service weavy

ClientApp/src/app/weavy.service.spec.ts
ClientApp/src/app/weavy.service.ts

Initializing the Weavy instance

We will create the Weavy instance in the service constructor and delay initialization to on demand to avoid slow rendering. The service will also handle the authentication.

You must declare Weavy to be able to reference it in the service, since it's defined globally.

We create a wrapper for the weavy.space() function for convenience and to initialize automatically on demand. You may also use all other functionality in Weavy, since we expose the Weavy instance as a property in the service.

To handle destruction simply just call weavy.destroy() in the ngOnDestroy hook. You need to import { OnDestroy } from '@angular/core' and also add class WeavyService implements OnDestroy.

weavy.service.ts

import { Injectable, OnDestroy } from '@angular/core';

// Weavy must be declared for usage
declare let Weavy: any;

@Injectable({
  providedIn: 'root'
})
export class WeavyService implements OnDestroy {

  initialized = false;

  jwt;
  weavy;

  constructor() {
    this.jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJsaWxseSIsIm5hbWUiOiJMaWxseSBEaWF6IiwiZXhwIjoyNTE2MjM5MDIyLCJpc3MiOiJzdGF0aWMtZm9yLWRlbW8iLCJjbGllbnRfaWQiOiJXZWF2eURlbW8iLCJkaXIiOiJjaGF0LWRlbW8tZGlyIiwiZW1haWwiOiJsaWxseS5kaWF6QGV4YW1wbGUuY29tIiwidXNlcm5hbWUiOiJsaWxseSJ9.rQvgplTyCAfJYYYPKxVgPX0JTswls9GZppUwYMxRMY0';
    this.weavy = new Weavy({ jwt: this.jwt, init: false });
  }

  init(): void {
    if (!this.initialized && !this.weavy.isInitialized) {
      this.weavy.init();
    }
    this.initialized = true;
  }

  space(selector: any) {
    this.init();
    return this.weavy.space(selector);
  }

  ngOnDestroy(): void {
    this.weavy.destroy();
  }
}

Configuring JWT

The JWT is for providing user authentication to Weavy. For this demo we use a static JWT that only works for the showcase server. The proper way to implement JWT is to create a service that you reference in your Weavy service class constructor. The service should then preferably just return a promise for the token.

See docs.weavy.com/client/authentication to read more about setting up JWT authentication.

Create the Weavy app component

You may also use the CLI to create a new component with inline template and styles. It will generate two files in ClientApp/src/app/weavy and adds the component to ClientApp/src/app/app.module.ts.

ng generate component weavy -t -s -m app

ClientApp/src/app/weavy/weavy.component.spec.ts
ClientApp/src/app/weavy/weavy.component.ts

Define a Weavy container

Add a div to the template section of ClientApp/src/app/weavy/weavy.component.ts. We take advantage of Angular #id to to pass the container rather than the id, to be able to reuse the component several times, otherwise a normal HTML id may only be used once. We also add a style class to make the layout of the div adapt to it's container rather than having it's own layout. The container must always have a defined size.

@Component({
  selector: 'app-weavy',
  template: '<div #weavyContainer class="weavy-container"></div>',
  styles: ['.weavy-container { display: contents; }']
})

Configure the container in your component class

You can bind Weavy options to component properties to be able to reuse your component. This is done using @Input() to decorate the properties. Note that you need to import { Input } from '@angular/core'.  The keys are then defined when using the component and may be anything you like.

@Input() spaceKey!: string;
@Input() spaceName!: string;

@Input() appType!: string;
@Input() appKey!: string;
@Input() appName!: string;

Since we used the angular #id, we need to also import { AfterViewInit, ViewChild, ElementRef } from '@angular/core' and add class WeavyComponent implements AfterViewInit. The element of the container can then be referenced as an ElementRef using @ViewChild() decorator.

@ViewChild('weavyContainer', null) weavyContainer!: ElementRef;

// The weavyContainer is not available until the view has been initialized
ngAfterViewInit() {
  console.log(this.weavyContainer!.nativeElement)
}

Using the Weavy service

To make use of the Weavy service we need to import { WeavyService } from '../weavy.service' in our component and then reference it in the constructor.

constructor(private weavy : WeavyService) { }

To handle destruction we just remove the Weavy app in the OnDestroy hook. You need to import { OnDestroy } from '@angular/core' and also add class WeavyComponent implements OnDestroy.

ngOnDestroy(): void {
  this.weavyApp!.remove();
}

Here is the complete component class

weavy.component.ts

import {
  Component, OnInit, OnDestroy,
  Input,
  AfterViewInit, ViewChild, ElementRef
} from '@angular/core';

import { WeavyService } from '../weavy.service';

@Component({
  selector: 'app-weavy',
  template: '<div #weavyContainer class="weavy-container"></div>',
  styles: ['.weavy-container { display: contents; }']
})
export class WeavyComponent implements OnInit, AfterViewInit, OnDestroy {
  @Input() spaceKey!: string;
  @Input() spaceName!: string;

  @Input() appType!: string;
  @Input() appKey!: string;
  @Input() appName!: string;

  @ViewChild('weavyContainer', null) weavyContainer!: ElementRef;

  weavySpace: any;
  weavyApp: any;

  constructor(private weavy: WeavyService) { }

  ngOnInit(): void {
    this.weavySpace = this.weavy.space({
      key: this.spaceKey,
      name: this.spaceName,
    })
  }

  ngAfterViewInit(): void {
    // After the view is initialized and the weavyContainer is available
    this.weavyApp = this.weavySpace.app({
      type: this.appType,
      key: this.appKey,
      name: this.appName,
      container: this.weavyContainer.nativeElement
    });
  }

  ngOnDestroy(): void {
    this.weavyApp!.remove();
  }
}

Using the Weavy component

To use the Weavy component simply reference it in any component template. You must always define the component properties with data for the weavy app. See angular.io/guide/inputs-outputs. Remember that the component needs to be placed in a container that has a defined size.

<div style="height: 32rem;">
  <app-weavy [spaceKey]="'angular-space'" [appType]="'files'" [appKey]="'my-files'" [appName]="'My files'"></app-weavy>
</div>

Create two demo pages

To demonstrate usage of the component we will creat two demo pages in the Angular app that will show both Weavy Files and Weavy Posts.

ng generate component files -s -m app

Now, just place a weavy component defining a files weavy-app in the files component template in ClientApp/src/app/files/files.component.html.

files.component.html

<h1>Files</h1>

<div style="height: 32rem;"> 
  <app-weavy [spaceKey]="'angular-space'" [appType]="'files'" [appKey]="'my-files'" [appName]="'My files'"></app-weavy>
</div>

Secondly we will create a corresponding posts component.

ng generate component posts -s -m app

Place a weavy component defining a posts weavy-app in the posts component template in ClientApp/src/app/posts/posts.component.html.

posts.component.html

<h1>Posts</h1>

<div style="height: 32rem;"> 
  <app-weavy [spaceKey]="'angular-space'" [appType]="'posts'" [appKey]="'my-posts'" [appName]="'Posts'"></app-weavy> 
</div>

To use the pages, we need to add them to the app routing in ClientApp/src/app/app.module.ts

app.module.ts

@NgModule({
  // ...
  imports: [
    // ...
    RouterModule.forRoot([
	  // ...
      { path: 'files', component: FilesComponent },
      { path: 'posts', component: PostsComponent },
    ])
  ],
})

Don't forget to add links to the pages in the nav menu component ClientApp/src/app/nav-menu/nav-menu.component.html.

nav-menu.component.html

<li class="nav-item" [routerLinkActive]="['link-active']">
  <a class="nav-link text-dark" [routerLink]="['/posts']">Posts</a>
</li>
<li class="nav-item" [routerLinkActive]="['link-active']">
  <a class="nav-link text-dark" [routerLink]="['/files']">Files</a>
</li>

Running the example

To test the example you can use dotnet run, which will compile and start a test server. It also recompiles and reloads the app in the browser whenever you make changes.

If you are using Visual Studio you can simply build and run using the play button (or F5).

After that, just open the app in your browser, usually on http://localhost:5000.

dotnet run

Voilà! Now you have a customizable Weavy component to integrate anywhere in your web app!

 

Learn more about Weavy Client SDK

 

Weavy

Share this post