4
votes

I am working on a project which was recently upgraded from Angular 5 to 6. I am adding a new feature which requires me to draw images from data, so I've been trying to use the Canvas and SVG DOM objects to do this. FabricJS has a lot of features I need.

I tried to add it to the project last night. I downloaded the full DEV/MIN versions of FabricJS from the website, v2.3.3. Then I made a "fabric" folder in my node_modules folder and put the *.js files there. I edited my angular.json file to include this:

    "scripts": [
      "node_modules/fabric/fabric.js"
    ]

Then created a typings.d.ts file with this:

declare const fabric: any;

Finally, in my module, I import it like this:

import * as fabric from 'fabric';

I put a canvas element on the page and named it "C"

<canvas id="c"></canvas>

And then try to use the fabric code:

        // create a wrapper around native canvas element (with id="c")
        const canvas = new fabric.Canvas('c');

When the fabric code gets executed, it throws an error:

***ERROR TypeError: fabric__WEBPACK_IMPORTED_MODULE_2__.Canvas is not a constructor
at SafeSubscriber._next***

I'm not really sure what this means. I spent some time looking for answers and didn't find very much on this, although I did find this page:

Fabric.js with Typescript and Webpack: Canvas is not a constructor

This sounds a lot like my issue, but I'm fairly new to Angular still and don't always understand what's going on. In that post, they discuss making changes to the webpack.mix.js file. I don't have such a file however, and I know that Angular 6 has a new version of WebPack, maybe that's breaking things?

Any thoughts on how to fix this? Where to start even?

2
You do have a webpack.config.js, right? Just add the rule that's in the answer and change your import statement to import fabric from 'fabric'. - Patrick Roberts
No, I don't. Angular 6 has WebPack "built in" to the CLI to try and stop newbs like myself from messing with what works. I saw some pages that mention how it might be done (ng-eject, but another post said that's removed now), however also lots of caveats about how this will change the build process and not to do it if you don't know what you are doing. I fall into the latter camp. - Todd Davis

2 Answers

1
votes

So the first thing to check is the import statement.

Fabric is imported as

import { fabric } from 'fabric';

For what regards webpack config and fabric in general, please have a look here:

https://github.com/fabricjs/fabricjs-webpack

Here you will find a configuration example to use the npm module directly if needed, or anyway it will help webpack to avoid trying to bundle node dependencies.

0
votes

I am using fabric as a global export following these steps:

  • run npm install fabric
  • Add to the scripts: ["node_modules/fabric/dist/fabric.js"]
  • Add it to the typings.d.ts: declare const fabric: any;
  • DO NOT IMPORT IT, just use it: const canvas = new fabric.Canvas('c');
  • profit

I think that the last part is the one you are missing if you add a library to the scripts in angular you then don't have to import it otherwise you will have 2 different copies of the library, if you want to use it as a module then you shouldn't add it to the scripts array. More info: https://github.com/angular/angular-cli/wiki/stories-global-scripts#using-global-libraries-inside-your-app

I hope this helps.