Reputation: 363
I'm building an Angular library and have been trying unsuccessfully to include a 3rd party JS library in it for quite some time. My setup looks like this:
project/
├─ angular-lib/
├─ angular-lib-demo-app/
I try to install plain-draggable, to be able to use it within Angular. I have installed plain-draggable via the npm i plain-draggable
command and declared it with declare let PlainDraggable: any;
in my component.ts file. Unfortunately, when I call the constructor I get the error message: ERROR ReferenceError: PlainDraggable is not defined
My method is as follows to get an idea of what I do in the case:
addNode() {
/**
* create node and set attributes
*/
let node = document.createElementNS("http://www.w3.org/2000/svg", "g");
let factory = this.componentFactoryResolver.resolveComponentFactory(NodeComponent);
let componentRef = factory.create(this.injector, [], node);
let dragNode = new PlainDraggable(node);
/**
* render node in angular view
*/
this.appRef.attachView(componentRef.hostView);
this.renderer.setAttribute(node, "ng-node", "");
this.renderer.setAttribute(node, "id", "node-" + (this.nodes.length+1))
this.renderer.appendChild(this.graph.nativeElement, node);
/**
* add node to graph data structure
*/
this.nodes.push(node);}
Except for the line with PlainDraggable, the rest works exactly as it should and is error-free. I have unfortunately only found very outdated tutorials and information regarding importing and including JS libraries in Angular. But unfortunately no recent ones that explicitly refer to Angular 12.
Maybe someone here can give some hints on what steps need to be followed so that not only the API is available, but the library is also packaged accordingly and I can include it in the angular-lib-demo-app.
Edit: I did try to add it to angular.json file like:
{"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"angular-lib": {
"projectType": "library",
"root": "projects/angular-lib",
"sourceRoot": "projects/angular-lib/src",
"prefix": "ng",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:ng-packagr",
"options": {
"scripts": [
{
"input": "projects/angular-lib/node_modules/plain-draggable/plain-draggable.min.js",
"inject": true,
"bundleName": "plain-draggable"
}
],
"tsConfig": "projects/angular-lib/tsconfig.lib.json",
"project": "projects/angular-lib/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "projects/angular-lib/tsconfig.lib.prod.json"
}
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/angular-lib/src/test.ts",
"tsConfig": "projects/angular-lib/tsconfig.spec.json",
"karmaConfig": "projects/angular-lib/karma.conf.js"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"projects/angular-lib/tsconfig.lib.json",
"projects/angular-lib/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"angular-lib-demo-app": {
"projectType": "application",
"schematics": {},
"root": "projects/angular-lib-demo-app",
"sourceRoot": "projects/angular-lib-demo-app/src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/angular-lib-demo-app",
"index": "projects/angular-lib-demo-app/src/index.html",
"main": "projects/angular-lib-demo-app/src/main.ts",
"polyfills": "projects/angular-lib-demo-app/src/polyfills.ts",
"tsConfig": "projects/angular-lib-demo-app/tsconfig.app.json",
"aot": true,
"assets": [
"projects/angular-lib-demo-app/src/favicon.ico",
"projects/angular-lib-demo-app/src/assets"
],
"styles": [
"projects/angular-lib-demo-app/src/styles.css"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "projects/angular-lib-demo-app/src/environments/environment.ts",
"with": "projects/angular-lib-demo-app/src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "angular-lib-demo-app:build"
},
"configurations": {
"production": {
"browserTarget": "angular-lib-demo-app:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "angular-lib-demo-app:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/angular-lib-demo-app/src/test.ts",
"polyfills": "projects/angular-lib-demo-app/src/polyfills.ts",
"tsConfig": "projects/angular-lib-demo-app/tsconfig.spec.json",
"karmaConfig": "projects/angular-lib-demo-app/karma.conf.js",
"assets": [
"projects/angular-lib-demo-app/src/favicon.ico",
"projects/angular-lib-demo-app/src/assets"
],
"styles": [
"projects/angular-lib-demo-app/src/styles.css"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"projects/angular-lib-demo-app/tsconfig.app.json",
"projects/angular-lib-demo-app/tsconfig.spec.json",
"projects/angular-lib-demo-app/e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "projects/angular-lib-demo-app/e2e/protractor.conf.js",
"devServerTarget": "angular-lib-demo-app:serve"
},
"configurations": {
"production": {
"devServerTarget": "angular-lib-demo-app:serve:production"
}
}
}
}
}
},
"defaultProject": "angular-lib"
}
But my IDE keeps telling me, that "Property scripts is not allowed." and by running ng build
ng-packagr says "Schema validation failed with the following errors: Data path "" must NOT have additional properties(scripts)."
I did a lot of research on that scripts injection part, but unfortunately was not able to find a working solution for this. Perhaps because it is a library project type. Any ideas, where to put it?
Upvotes: 3
Views: 2260
Reputation: 363
I made it work! Apparently it seems, that you can't assign dependencies to an Angular library via angular.json using the scripts field. You have to do that in the project where you use the library.
I included the following code in the part of my demo application and when I launch it, the dependency is resolved and loaded.
Note: projectType is "application".
"angular-lib-demo-app": {
"projectType": "application",
"schematics": {},
"root": "projects/angular-lib-demo-app",
"sourceRoot": "projects/angular-lib-demo-app/src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/angular-lib-demo-app",
"index": "projects/angular-lib-demo-app/src/index.html",
"main": "projects/angular-lib-demo-app/src/main.ts",
"polyfills": "projects/angular-lib-demo-app/src/polyfills.ts",
"tsConfig": "projects/angular-lib-demo-app/tsconfig.app.json",
"aot": true,
"assets": [
"projects/angular-lib-demo-app/src/favicon.ico",
"projects/angular-lib-demo-app/src/assets"
],
"styles": [
"projects/angular-lib-demo-app/src/styles.css"
],
"scripts": [{
"input": "projects/angular-lib/node_modules/plain-draggable/plain-draggable.min.js",
"inject": true,
"bundleName": "plain-draggable"
}] ...
Upvotes: 4