# Using vtk.js in an angular app

**URL:** https://discourse.vtk.org/t/using-vtk-js-in-an-angular-app/3909
**Category:** Web
**Created:** [August 4, 2020, 3:46pm UTC](https://discourse.vtk.org/t/using-vtk-js-in-an-angular-app/3909 "2020-08-04T15:46:25Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![Ramu](https://discourse.vtk.org/user_avatar/discourse.vtk.org/ramu/32/2163_2.png) [@Ramu](https://discourse.vtk.org/u/Ramu)
#### Post date: [August 4, 2020, 3:46pm UTC](https://discourse.vtk.org/t/using-vtk-js-in-an-angular-app/3909/1 "2020-08-04T15:46:25Z")

</div>

I am using Geometry viewer in my angular app. I embedded the html page inside my application without any imports. I want to extend the viewer capabilities so I wish to use vtk.js and build things from scratch.

I tried to look at the documentation but I couldn’t find any helpful guide. I installed the node modules in my angular app but have difficulty in importing and using it. Also is there any types support in vtk.js when using Typescript ?

---

<div class="post-metadata">

### Author: ![Sebastien\_Jourdain](https://discourse.vtk.org/user_avatar/discourse.vtk.org/sebastien_jourdain/32/100_2.png) [@Sebastien\_Jourdain](https://discourse.vtk.org/u/Sebastien_Jourdain)
#### Post date: [August 4, 2020, 4:47pm UTC](https://discourse.vtk.org/t/using-vtk-js-in-an-angular-app/3909/2 "2020-08-04T16:47:44Z")

</div>

We have very few types in vtk.js that have been defined using TypeScript.  
This is something we would like to pursue but we keep having other priority that push that further back in time.

Regarding angular integration, and how to import it, I’m not sure what are the difficulties you are facing. The docs are mostly for general JS usage which should still be true for any framework.

Rules needs to be defined so vtk.js/Sources/\*\* can be properly handled.  
Those rules have been extracted in many format but most likely not the way Angular is expecting them. But they should give you enough to figure out what need to happen in your framework of predilection. You can look at them in that [directory](https://github.com/Kitware/vtk-js/tree/master/Utilities/config).

And here are the various example on how to use vtk.js from Sources

- [https://kitware.github.io/vtk-js/docs/intro\_vtk\_as\_es6\_dependency.html](https://kitware.github.io/vtk-js/docs/intro_vtk_as_es6_dependency.html)
- [https://github.com/Kitware/web-project-templates/blob/master/vue-vtkjs-template/vue.config.js#L9](https://github.com/Kitware/web-project-templates/blob/master/vue-vtkjs-template/vue.config.js#L9)

HTH,

Seb

---

<div class="post-metadata">

### Author: ![Donny\_Zimmerman](https://discourse.vtk.org/user_avatar/discourse.vtk.org/donny_zimmerman/32/301_2.png) [@Donny\_Zimmerman](https://discourse.vtk.org/u/Donny_Zimmerman)
#### Post date: [August 5, 2020, 3:37pm UTC](https://discourse.vtk.org/t/using-vtk-js-in-an-angular-app/3909/3 "2020-08-05T15:37:48Z")

</div>

Here is a Typescript file I created that utilizes vtk.js

> [@](#):
>
> import vtkActor from ‘vtk.js/Sources/Rendering/Core/Actor’;  
> import vtkMapper from ‘vtk.js/Sources/Rendering/Core/Mapper’;  
> import vtkOpenGLRenderWindow from ‘vtk.js/Sources/Rendering/OpenGL/RenderWindow’;  
> import vtkRenderWindow from ‘vtk.js/Sources/Rendering/Core/RenderWindow’;  
> import vtkCamera from ‘vtk.js/Sources/Rendering/Core/Camera’;  
> import vtkRenderWindowInteractor from ‘vtk.js/Sources/Rendering/Core/RenderWindowInteractor’;  
> import vtkRenderer from ‘vtk.js/Sources/Rendering/Core/Renderer’;  
> //import vtkInteractorStyleTrackballCamera from ‘vtk.js/Sources/Interaction/Style/InteractorStyleTrackballCamera’;  
> import vtkInteractorStyleTrackballCamera from ‘vtk.js/Sources/Interaction/Style/InteractorStyleRadarCamera’;  
> //import vtkInteractorStyleRadarCamera from ‘vtk.js/Sources/Interaction/Style/InteractorStyleRadarCamera’;  
> import vtkMath from ‘vtk.js/Sources/Common/Core/Math’;  
> import vtkTexture from ‘vtk.js/Sources/Rendering/Core/Texture’;  
> import vtkXMLPolyDataReader from ‘vtk.js/Sources/IO/XML/XMLPolyDataReader’;  
> import { vec3, quat, mat3, mat4 } from ‘gl-matrix’;
> 
> import RadialImgRadarProduct = require(‘./radar\_img\_radial\_product’)  
> import RadialRpgRadarProduct = require(‘./radar\_rpg\_radial\_product’)
> 
> class RadarRenderWindow {
> 
> ```
> private radialRadarProduct1;
> private radialRadarProduct2;
> 
> private siteLat: number;
> private siteLon: number;
> 
> private loopIndex: number = 0;
> 
> private renderWindow = vtkRenderWindow.newInstance();
> private openGlRenderWindow = vtkOpenGLRenderWindow.newInstance();
> 
> private renCam = vtkCamera.newInstance();
> private globeRenderer1 = vtkRenderer.newInstance({ background: [0, 0, 0] });
> private radarRenderer1 = vtkRenderer.newInstance({ background: [0, 0, 0] });
> private mapRenderer1 = vtkRenderer.newInstance({ background: [0, 0, 0] });
> 
> private globeRenderer2 = vtkRenderer.newInstance({ background: [0, 0, 0] });
> private radarRenderer2 = vtkRenderer.newInstance({ background: [0, 0, 0] });
> private mapRenderer2 = vtkRenderer.newInstance({ background: [0, 0, 0] });
> 
> /*private globeRenderer3 = vtkRenderer.newInstance({ background: [0, 0, 0] });
> private radarRenderer3 = vtkRenderer.newInstance({ background: [0, 0, 0] });
> private mapRenderer3 = vtkRenderer.newInstance({ background: [0, 0, 0] });
> 
> private globeRenderer4 = vtkRenderer.newInstance({ background: [0, 0, 0] });
> private radarRenderer4 = vtkRenderer.newInstance({ background: [0, 0, 0] });
> private mapRenderer4 = vtkRenderer.newInstance({ background: [0, 0, 0] });*/
> 
> private globeActor = vtkActor.newInstance();
> private globeMapper = vtkMapper.newInstance();
> 
> private mapActor = vtkActor.newInstance();
> private mapMapper = vtkMapper.newInstance();
> 
> private interactor = vtkRenderWindowInteractor.newInstance();
> 
> private numRadarLoopProds = 12;
> 
> public radarLoopLoadedCallback: () => void;
> public radarLoadingProgressCallback: (ev: ProgressEvent<EventTarget>, index: number) => void;
> public radarLoadingStartCallback: (index: number) => void;
> public radarLoadingEndCallback: () => void;
> 
> public constructor(numlayers: number, numprods: number, rproctype: number) {
> 
> this.numRadarLoopProds = numprods;
> 
> this.renderWindow.addView(this.openGlRenderWindow);
> this.renderWindow.setNumberOfLayers(numlayers);
> 
> this.renCam.setClippingRange(10000.0, 10000000.0);
> 
> this.globeRenderer1.setLayer(0);
> this.globeRenderer1.setActiveCamera(this.renCam);
> //this.globeRenderer1.setViewport(0.001, 0.51, 0.495, 0.99);
> this.globeRenderer1.setViewport(0.001, 0.01, 0.495, 0.99);
> 
> this.globeRenderer2.setLayer(0);
> this.globeRenderer2.setActiveCamera(this.renCam);
> //this.globeRenderer2.setViewport(0.501, 0.51, 0.995, 0.99);
> this.globeRenderer2.setViewport(0.501, 0.01, 0.995, 0.99);
> 
> /*this.globeRenderer3.setLayer(0);
> this.globeRenderer3.setActiveCamera(this.renCam);
> this.globeRenderer3.setViewport(0.001, 0.01, 0.495, 0.49);
> 
> this.globeRenderer4.setLayer(0);
> this.globeRenderer4.setActiveCamera(this.renCam);
> this.globeRenderer4.setViewport(0.501, 0.01, 0.995, 0.49);*/
> 
> this.radarRenderer1.setLayer(1);
> this.radarRenderer1.setActiveCamera(this.renCam);
> this.radarRenderer1.setPreserveDepthBuffer(true);
> //this.radarRenderer1.setViewport(0.001, 0.51, 0.495, 0.99);
> this.radarRenderer1.setViewport(0.001, 0.01, 0.495, 0.99);
> 
> this.radarRenderer2.setLayer(1);
> this.radarRenderer2.setActiveCamera(this.renCam);
> this.radarRenderer2.setPreserveDepthBuffer(true);
> //this.radarRenderer2.setViewport(0.501, 0.51, 0.995, 0.99);
> this.radarRenderer2.setViewport(0.501, 0.01, 0.995, 0.99);
> 
> /*this.radarRenderer3.setLayer(1);
> this.radarRenderer3.setActiveCamera(this.renCam);
> this.radarRenderer3.setPreserveDepthBuffer(true);
> this.radarRenderer3.setViewport(0.001, 0.01, 0.495, 0.49);
> 
> this.radarRenderer4.setLayer(1);
> this.radarRenderer4.setActiveCamera(this.renCam);
> this.radarRenderer4.setPreserveDepthBuffer(true);
> this.radarRenderer4.setViewport(0.501, 0.01, 0.995, 0.49);*/
> 
> this.mapRenderer1.setLayer(2);
> this.mapRenderer1.setActiveCamera(this.renCam);
> //this.mapRenderer1.setViewport(0.001, 0.51, 0.495, 0.99);
> this.mapRenderer1.setViewport(0.001, 0.01, 0.495, 0.99);
> 
> this.mapRenderer2.setLayer(2);
> this.mapRenderer2.setActiveCamera(this.renCam);
> //this.mapRenderer2.setViewport(0.501, 0.51, 0.995, 0.99);
> this.mapRenderer2.setViewport(0.501, 0.01, 0.995, 0.99);
> 
> /*this.mapRenderer3.setLayer(2);
> this.mapRenderer3.setActiveCamera(this.renCam);
> this.mapRenderer3.setViewport(0.001, 0.01, 0.495, 0.49);
> 
> this.mapRenderer4.setLayer(2);
> this.mapRenderer4.setActiveCamera(this.renCam);
> this.mapRenderer4.setViewport(0.501, 0.01, 0.995, 0.49);*/
> 
> this.renderWindow.addRenderer(this.globeRenderer1);
> this.renderWindow.addRenderer(this.globeRenderer2);
> /*this.renderWindow.addRenderer(this.globeRenderer3);
> this.renderWindow.addRenderer(this.globeRenderer4);*/
> 
> this.renderWindow.addRenderer(this.radarRenderer1);
> this.renderWindow.addRenderer(this.radarRenderer2);
> /*this.renderWindow.addRenderer(this.radarRenderer3);
> this.renderWindow.addRenderer(this.radarRenderer4);*/
> 
> this.renderWindow.addRenderer(this.mapRenderer1);
> this.renderWindow.addRenderer(this.mapRenderer2);
> /*this.renderWindow.addRenderer(this.mapRenderer3);
> this.renderWindow.addRenderer(this.mapRenderer4);*/
> 
> if (rproctype === 2) {
> this.radialRadarProduct1 = new RadialRpgRadarProduct(numprods, this.radarRenderer1);
> this.radialRadarProduct2 = new RadialRpgRadarProduct(numprods, this.radarRenderer2);
> 
> } else {
> 
> this.radialRadarProduct1 = new RadialImgRadarProduct(numprods, this.radarRenderer1);
> this.radialRadarProduct2 = new RadialImgRadarProduct(numprods, this.radarRenderer2);
> }
>     
> 
> }
> 
> public setSize(width: number, height: number): void {
> 
> this.openGlRenderWindow.setSize(width, height);
> }
> 
> public initializeInteractor(rootContainer: HTMLElement): void {
> 
> this.openGlRenderWindow.setContainer(rootContainer);
> this.interactor.setView(this.openGlRenderWindow);
> this.interactor.initialize();
> this.interactor.bindEvents(rootContainer);
> 
> this.interactor.setInteractorStyle(vtkInteractorStyleTrackballCamera.newInstance());
> 
> }
> 
> public setRadarColorTable1(colors: Uint8Array): void {
> 
> this.radialRadarProduct1.setRadarColorTable(colors);
> }
> 
> public setRadarColorTable2(colors: Uint8Array): void {
> 
> this.radialRadarProduct2.setRadarColorTable(colors);
> }
> 
> public connectGlobePolydata(fileContents: any): void {
> 
> const vtpReader = vtkXMLPolyDataReader.newInstance();
> vtpReader.parseAsArrayBuffer(fileContents);
> this.globeMapper.setInputConnection(vtpReader.getOutputPort());
> 
> }
> 
> public connectGlobeTexture(imageElement: HTMLImageElement): void {
> 
> const globeTexture = vtkTexture.newInstance();
> globeTexture.setRepeat(true);
> globeTexture.setImage(imageElement);
> this.globeActor.addTexture(globeTexture);
> 
> this.globeActor.setMapper(this.globeMapper);
> this.globeActor.getProperty().setLighting(false);
> this.globeRenderer1.addActor(this.globeActor);
> this.globeRenderer2.addActor(this.globeActor);
> /*this.globeRenderer3.addActor(this.globeActor);
> this.globeRenderer4.addActor(this.globeActor);*/
> 
> }
> 
> public setInitialCameraConfiguration(): void {
> 
> let erm = 6356750.0;
> 
> let radwp = this.computeGlobePoint(this.siteLon, this.siteLat, erm);
> 
> this.renCam.setViewUp(radwp[0], radwp[1], radwp[2]);
> 
> let positionVector = vec3.create();
> positionVector[0] = radwp[0];
> positionVector[1] = radwp[1];
> positionVector[2] = radwp[2];
> 
> vtkMath.multiplyScalar(positionVector, 1.15);
> this.setCameraPosition(positionVector[0], positionVector[1], positionVector[2] - 1000.0);
> 
> this.setCameraFocalPoint(radwp[0], radwp[1], radwp[2]);
> this.render();
> }
> 
> public connectCountyLinePolydata(fileContents: any): void {
> 
> const vtpCountyLineReader = vtkXMLPolyDataReader.newInstance();
> vtpCountyLineReader.parseAsArrayBuffer(fileContents);
> 
> this.mapMapper.setInputConnection(vtpCountyLineReader.getOutputPort());
> 
> this.mapActor.setMapper(this.mapMapper);
> this.mapActor.getProperty().setLighting(false);
> this.mapRenderer1.addActor(this.mapActor);
> this.mapRenderer2.addActor(this.mapActor);
> /*this.mapRenderer3.addActor(this.mapActor);
> this.mapRenderer4.addActor(this.mapActor);*/
> }
> 
> public setCameraPosition(posx: number, posy: number, posz: number): void {
> 
> this.renCam.setPosition(posx, posy, posz);
> this.renCam.elevation(-1);
> }
> 
> public setCameraFocalPoint(posx: number, posy: number, posz: number): void {
> 
> this.renCam.setFocalPoint(posx, posy, posz);
> 
> }
> 
> private render(): void {
> 
> this.renderWindow.render();
> }
> 
> loadIntitialRadarLoop1(rpgProducts: any): void {
> 
> this.siteLat = rpgProducts[0].LatitudeOfRadar / 1000.0;
> this.siteLon = rpgProducts[0].LongitudeOfRadar / 1000.0;
> 
> this.setInitialCameraConfiguration();
> 
> let base = this;
> 
> this.radialRadarProduct1.productLoopLoadedCallback = function () {
> base.render();
> base.radarLoopLoadedCallback();
> }
> 
> this.radialRadarProduct1.productLoadingStartCallback = function (index) {
> 
> base.radarLoadingStartCallback(index);
> }
> 
> this.radialRadarProduct1.productLoadingProgressCallback = function (ev, index) {
> 
> base.radarLoadingProgressCallback(ev, index);
> }
> 
> this.radialRadarProduct1.productLoadingEndCallback = function () {
> base.render();
> base.radarLoadingEndCallback();
> }
> 
> this.radialRadarProduct1.loadIntitialRadarLoop(rpgProducts);
> }
> 
> loadIntitialRadarLoop2(rpgProducts: any, view: number): void {
> 
> let base = this;
> 
> this.radialRadarProduct2.productLoopLoadedCallback = function () {
> base.render();
> //base.radarLoopLoadedCallback();
> }
> 
> this.radialRadarProduct2.productLoadingStartCallback = function (index) {
> 
> //base.radarLoadingStartCallback(index);
> }
> 
> this.radialRadarProduct2.productLoadingProgressCallback = function (ev, index) {
> 
> //base.radarLoadingProgressCallback(ev, index);
> }
> 
> this.radialRadarProduct2.productLoadingEndCallback = function () {
> 
> base.render();
> //base.radarLoadingEndCallback();
> }
> 
> this.radialRadarProduct2.loadIntitialRadarLoop(rpgProducts);
> }
> 
> public base64Encode(inputStr): string {
> var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
> var outputStr = "";
> var i = 0;
> 
> while (i < inputStr.length) {
> //all three "& 0xff" added below are there to fix a known bug 
> //with bytes returned by xhr.responseText
> var byte1 = inputStr.charCodeAt(i++) & 0xff;
> var byte2 = inputStr.charCodeAt(i++) & 0xff;
> var byte3 = inputStr.charCodeAt(i++) & 0xff;
> 
> var enc1 = byte1 >> 2;
> var enc2 = ((byte1 & 3) << 4) | (byte2 >> 4);
> 
> var enc3, enc4;
> if (isNaN(byte2)) {
> enc3 = enc4 = 64;
> }
> else {
> enc3 = ((byte2 & 15) << 2) | (byte3 >> 6);
> if (isNaN(byte3)) {
> enc4 = 64;
> }
> else {
> enc4 = byte3 & 63;
> }
> }
> 
> outputStr += b64.charAt(enc1) + b64.charAt(enc2) + b64.charAt(enc3) + b64.charAt(enc4);
> }
> 
> return outputStr;
> }
> 
> public showNextRadarFrame(): boolean {
> 
> let genDate = this.radialRadarProduct1.showRadarFrame(this.loopIndex);
> this.radialRadarProduct2.showRadarFrame(this.loopIndex);
> this.render();
> 
> let genDateTime = document.getElementById('generationDate');
> genDateTime.innerHTML = "Generated On: " + genDate;
> 
> this.loopIndex++;
> 
> if (this.loopIndex >= this.radialRadarProduct1.getNumberOfActors()) {
> this.loopIndex = 0;
> return true;
> }
> else {
> return false;
> }
> }
> 
> public processNewRadarProduct(p1: any, view: number) {
> 
> if (view === 2) {
> this.radialRadarProduct2.processNewRadarProduct(p1);
> 
> } else {
> 
> this.radialRadarProduct1.processNewRadarProduct(p1);
> }
> 
> }
> 
> private computeGlobePoint(theta, phi, radius): number {
> 
> // Lets keep this conversion code in a single place.
> let tmp = Math.cos(vtkMath.radiansFromDegrees(phi));
> let n0 = -tmp * Math.sin(vtkMath.radiansFromDegrees(theta));
> let n1 = tmp * Math.cos(vtkMath.radiansFromDegrees(theta));
> let n2 = Math.sin(vtkMath.radiansFromDegrees(phi));
> 
> var v = vec3.fromValues(n0 * radius, n1 * radius, n2 * radius);
> return v;
> }
> 
> ```
> 
> }
> 
> export = RadarRenderWindow;

---

<div class="post-metadata">

### Author: ![Ramu](https://discourse.vtk.org/user_avatar/discourse.vtk.org/ramu/32/2163_2.png) [@Ramu](https://discourse.vtk.org/u/Ramu)
#### Post date: [August 13, 2020, 9:10am UTC](https://discourse.vtk.org/t/using-vtk-js-in-an-angular-app/3909/4 "2020-08-13T09:10:58Z")

</div>

Thanks @Sebastien_Jourdain for your pointers. I have some experience with angular and no experience with js. I tried to read on modern web development with webpack. I tried to follow the es6\_dependency example and was able to start a standalone project. Now I am trying to do the same in angular. I tried to create an angular component based on @Donny_Zimmerman example and when I build it I get the following error

```
ERROR in ./node_modules/vtk.js/Sources/Rendering/OpenGL/glsl/vtkVolumeVS.glsl 18:10
Module parse failed: Unexpected token (18:10)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| =========================================================================*/
| 
> attribute vec4 vertexDC;
| 
| varying vec3 vertexVCVSOutput;

```

(above is part of the error stack, let me know if you need complete error stack)

I created my typescript file as following

```
import { Component, OnInit } from '@angular/core';

import vtkConeSource from 'vtk.js/Sources/Filters/Sources/ConeSource';
import vtkInteractorStyleTrackballCamera from 'vtk.js/Sources/Interaction/Style/InteractorStyleTrackballCamera';
import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor';
import vtkMapper from 'vtk.js/Sources/Rendering/Core/Mapper';
import vtkRenderer from 'vtk.js/Sources/Rendering/Core/Renderer';
import vtkRenderWindow from 'vtk.js/Sources/Rendering/Core/RenderWindow';
import vtkRenderWindowInteractor from 'vtk.js/Sources/Rendering/Core/RenderWindowInteractor';
import vtkOpenGLRenderWindow from 'vtk.js/Sources/Rendering/OpenGL/RenderWindow';

@Component({
  selector: 'nse-geometry-viewer-es6',
  styleUrls: ['./geometry-viewer-es6.component.scss'],
  templateUrl: './geometry-viewer-es6.component.html'
})
export class GeometryViewerEs6Component implements OnInit {
  constructor() {}

  public ngOnInit() {
    const container = document.querySelector('#container');

    // VTK renderWindow/renderer
    const renderWindow = vtkRenderWindow.newInstance();
    const renderer = vtkRenderer.newInstance();
    renderWindow.addRenderer(renderer);

    // WebGL/OpenGL impl
    const openGLRenderWindow = vtkOpenGLRenderWindow.newInstance();
    openGLRenderWindow.setContainer(container);
    openGLRenderWindow.setSize(1000, 1000);
    renderWindow.addView(openGLRenderWindow);

    // Interactor
    const interactor = vtkRenderWindowInteractor.newInstance();
    interactor.setView(renderWindow);
    interactor.initialize();
    interactor.bindEvents(container);

    // Interactor style
    const trackball = vtkInteractorStyleTrackballCamera.newInstance();
    interactor.setInteractorStyle(trackball);

    // Pipeline
    const cone = vtkConeSource.newInstance();
    const actor = vtkActor.newInstance();
    const mapper = vtkMapper.newInstance();

    actor.setMapper(mapper);
    mapper.setInputConnection(cone.getOutputPort());
    renderer.addActor(actor);

    // Render
    renderer.resetCamera();
    renderWindow.render();
  }
}

```

I installed `vtk.js` from npm but I don’t know how to configure webpack for vtkjs (Do we need to replace `@angular-devkit/build-angular` with some custom webpack ?)

---

<div class="post-metadata">

### Author: ![Sebastien\_Jourdain](https://discourse.vtk.org/user_avatar/discourse.vtk.org/sebastien_jourdain/32/100_2.png) [@Sebastien\_Jourdain](https://discourse.vtk.org/u/Sebastien_Jourdain)
#### Post date: [August 13, 2020, 3:38pm UTC](https://discourse.vtk.org/t/using-vtk-js-in-an-angular-app/3909/5 "2020-08-13T15:38:15Z")

</div>

So the missing part is the registration of vtk.js rules within your angular/webpack infrastructure. And I don’t know how you can extends those rules within angular.

Vue.js has a chain mechanism for it. But That’s about what I know.

---

<div class="post-metadata">

### Author: ![Ramu](https://discourse.vtk.org/user_avatar/discourse.vtk.org/ramu/32/2163_2.png) [@Ramu](https://discourse.vtk.org/u/Ramu)
#### Post date: [August 19, 2020, 5:04pm UTC](https://discourse.vtk.org/t/using-vtk-js-in-an-angular-app/3909/6 "2020-08-19T17:04:29Z")

</div>

@Sebastien_Jourdain, I was able to use vtk.js in angular project with guidance from Forrest Li, here is the link from vtk.js github issues [https://github.com/Kitware/vtk-js/issues/1003#issuecomment-676477880](https://github.com/Kitware/vtk-js/issues/1003#issuecomment-676477880)

Can we have this in documentation ?

It took me lot a time to get to this point and still I couldn’t figure it out on how to configure rules. Thanks to minimal reproduction from Forrest Li, I am now able to use it in my project. I feel it would be a good idea to have it in documentation.

I am open to contribute in ways possible to have this example in vtk.js documentation.

---

<div class="post-metadata">

### Author: ![Ramu](https://discourse.vtk.org/user_avatar/discourse.vtk.org/ramu/32/2163_2.png) [@Ramu](https://discourse.vtk.org/u/Ramu)
#### Post date: [August 19, 2020, 5:06pm UTC](https://discourse.vtk.org/t/using-vtk-js-in-an-angular-app/3909/7 "2020-08-19T17:06:45Z")

</div>

Thanks to **[@floryst](https://github.com/floryst)** , works with this example [https://github.com/Kitware/vtk-js/issues/1003#issuecomment-676477880](https://github.com/Kitware/vtk-js/issues/1003#issuecomment-676477880)
