Annotating classes - javascript

I would like to use annotate classes in my javascript project. I'm using webpack and everything looks working (project compiles) but annotated classes fails to execute.
function annotation(target) {
target.isAnnotated = true;
}
#annotation()
export class Template {
constructor(id, name, subject, type) {
this.id = id;
this.name = name;
this.subject = subject;
this.type = type;
this.message = '';
}
}
My webpack.config.js uses such configuration options:
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
plugins: [
["#babel/plugin-proposal-decorators", { "legacy": true }]
]
}
}
but while runing the code, I get the exception:
Cannot set property 'isAnnotated' of undefined
Either I can't properly create annotation function or there is something more I need to configure but based on this it should be working.

Related

ES6/Babel Class constructor cannot be invoked without 'new'

I'm trying to create a custom Quill theme, extending the bubble one. I'm facing a strange ES6 inheritance problem, where it seems I cannot call super() in my constructor. Here is my code:
import BubbleTheme, { BubbleTooltip } from 'quill/themes/bubble'
class LoopTheme extends BubbleTheme {
constructor (quill, options) {
super(quill, options)
}
extendToolbar (toolbar) {
super.extendToolbar(toolbar)
this.tooltip = new LoopTooltip(this.quill, this.options.bounds);
this.tooltip.root.appendChild(toolbar.container);
}
}
class LoopTooltip extends BubbleTooltip {
}
LoopTooltip.TEMPLATE = [
'<span class="ql-tooltip-arrow"></span>',
'<div class="ql-tooltip-editor">',
'<input type="text" data-formula="e=mc^2" data-link="https://myurl.com" data-video="Embed URL">',
'<a class="ql-close"></a>',
'</div>'
].join('');
export { LoopTooltip, LoopTheme as default }
Bubble theme could be found here
My Babel presets:
{
"presets": [
"es2015",
"es2016",
"stage-0",
"react"
]
}
Webpack js file config:
module: {
rules: [
{
test: /\.js$/,
include: [
resolve(__dirname, 'app')
],
loader: 'babel-loader',
exclude: /node_modules/
}, {...
Output generated code:
var LoopTheme = function (_BubbleTheme) {
_inherits(LoopTheme, _BubbleTheme);
function LoopTheme() {
_classCallCheck(this, LoopTheme);
return _possibleConstructorReturn(this, (LoopTheme.__proto__ || Object.getPrototypeOf(LoopTheme)).apply(this, arguments));
}
_createClass(LoopTheme, [{
key: 'extendToolbar',
value: function extendToolbar(toolbar) {
_get(LoopTheme.prototype.__proto__ || Object.getPrototypeOf(LoopTheme.prototype), 'extendToolbar', this).call(this, toolbar);
this.tooltip = new LoopTooltip(this.quill, this.options.bounds);
this.tooltip.root.appendChild(toolbar.container);
}
}]);
return LoopTheme;
}(_bubble2.default);
var LoopTooltip = function (_BubbleTooltip) {
_inherits(LoopTooltip, _BubbleTooltip);
function LoopTooltip() {
_classCallCheck(this, LoopTooltip);
return _possibleConstructorReturn(this, (LoopTooltip.__proto__ || Object.getPrototypeOf(LoopTooltip)).apply(this, arguments));
}
return LoopTooltip;
}(_bubble.BubbleTooltip);
LoopTooltip.TEMPLATE = ['<span class="ql-tooltip-arrow"></span>', '<div class="ql-tooltip-editor">', '<input type="text" data-formula="e=mc^2" data-link="myurl.com" data-video="Embed URL">', '<a class="ql-close"></a>', '</div>'].join('');
exports.LoopTooltip = LoopTooltip;
exports.default = LoopTheme;
I'm having the following error: events.js:59 Uncaught TypeError: Class constructor BubbleTheme cannot be invoked without 'new'. However, the LoopTheme is correctly called with new by Quill here. When I debug step by step, I correctly enter the LoopTheme constructor, and the error is raised when super is called.
Am I missing something here? I've always used inheritance, and I use it elsewhere in my code (between my classes), where here am I having trouble?
Thanks for your help
I ran into the exact same issue while extending Quill’s BaseTheme.
As Bergi correctly pointed out in the comments above, this has to do with the fact that babel-loader isn’t transpiling Quill’s modules because they're inside node_modules/, which is excluded.
You can either update the exclude option in your Webpack config and use a regex to skip the node_modules/quill/ folder or use include instead:
{
test: /\.js$/,
loader: 'babel-loader',
include: [
path.join(__dirname, '../src'), // + any other paths that need to be transpiled
/\/node_modules\/quill/,
]
}
You can also replace this:
import BubbleTheme from 'quill/themes/bubble'
into this:
const BubbleTheme = Quill.import('themes/bubble')
I would like to suggest another way. In case you are not building quill in you pipe line, you could very well reference the runtime constructor above the extended class.
import { sanitize } from 'quill/formats/link';
let BlockEmbed = window['Quill'].import('blots/block/embed');
export class MediaBlot extends BlockEmbed {
...
}

Object is not defined after Webpack bundling

I have simple app wrote in ES6 for the training purpose. I want to use modules in this app, so I installed webpack and babel. Unfortunetaly, when I try to fire my method, I receive the error:
Uncaught ReferenceError: gas is not defined
at HTMLButtonElement.count (bundle.js:113)
So, 'gas' is my instance of the object.
Here are my files:
main.js
'use strict'
import Gas from "./gas";
const count = document.getElementById("gas-count");
const gas = new Gas();
count.addEventListener("click", gas.count);
gas.js
export default class Gas {
constructor() {
}
count() {
// code
}
printResult(result) {
// code
}
_isValid(dist, price, aver) {
// Code
}
};
Finally, here is my Webpack config:
module.exports = {
// Define entry point
entry: "./src/main.js",
// Define output point
output: {
path: __dirname + "/dist",
filename: "bundle.js"
},
module: {
loaders: [{
test: /\.js$/,
exclude: /(node_modules)/,
loader: "babel-loader",
query: {
presets: ["env"]
}
}]
}
};
I'd be really grateful if someone could give me a hint why it's not working. Thank you in advance.

How to expose an es6 module globally

I need to write a module that will be available on the window global.
I'm using es6 to create the module and every single class I define has it's own file.
I'm using webpack to babelify and bundle these classes.
The entry point of my module is also the file containing the global to be exposed.
I've tried every method to make this possibe, icluding:
expose-loader
import-loader
expoert-loader
output: library
black-magic :(
Example of code I've tried:
I want to get: window.MyMod
// mymod.js
export class MyMod {
constructor(aaa) {
this.aaa = aaa;
}
toString() {
return this.aaa;
}
}
// webpack.config
var entries = [
'./src/mymod.js'
];
module.exports = {
...,
module: {
loaders: [
{
test: require.resolve('./src/mymod.js'),
loader: 'expose?MyMod'
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}
]
}
This only gets me an object MyMod on the window that contains MyMod as a constructor.
Any help will be appreciated.
You should combine export default class Foo with the library and libraryTarget settings in Webpack's config. Something like:
// src/Foo.js
export default class Foo { ... }
// webpack.config.json
{
"output": {
"library": "Foo",
"libraryTarget": "var"
}
}
You should be able to use the library as window.Foo once the bundle has been loaded.
This is basically the same issue as Exporting a class with Webpack and Babel not working , except that you have a named export instead of a default export. Your entry file should be
import {MyMod} from './mymod';
module.exports = MyMod;
or
module.exports = require('./mymod').MyMod;
If you don't want to do any of these and keep './src/mymod.js' as entry file, use a CommonJS export instead of an ES6 export in that file:
// mymod.js
exports.MyMod = class MyMod {
constructor(aaa) {
this.aaa = aaa;
}
toString() {
return this.aaa;
}
}

New Class from IIFE function now working with webpack

So i have this function. I am trying to get a new Test('selector', {}) from outside this js file, it comes undefined and i can't seem to figure out why.
Do i really need to attach it to the window object ?
Can someone explain this ?
TO mention it works from the same file.
let Test = ((window, document, undefined) => {
class test {
constructor(selector, options) {
this.selector = document.querySelector(selector);
this.options = options;
}
}
return test;
})(window, document);
This is my webpack config file:
module.exports = {
entry: './src/test.js',
module: {
loaders: [
{
test: /\.js?$/,
exclude: / (node_modules) /,
loader: 'babel-loader',
query: {
presets: ['es2015', 'stage-0']
}
}
]
},
output: {
path: __dirname + '/src',
filename: 'test.min.js'
}
}
I was clearly misunderstanding what webpack is doing. Webpack turns all your JavaScript files into modules that are not available in the global namespace. That's why we need to use require/import to load them in. In the above example the Test function was never loaded in and is not defined. The default scoping nature of JavaScript no longer exists.

Typescript: can't compile file with : notation in constructor

I'm following some examples of a Ionic (with Angular 2) app.
All classes' constructor have something like:
export class UserService {
constructor(http: Http) {
this.http = http;
}
}
but the compiler outputs this error:
Unexpected token (14:17)
12 | }
13 |
> 14 | constructor(http: Http)
at Parser.pp.raise (/home/cbenseler/dev/apps/expressoapp/node_modules/babylon/index.js:1425:13)
This is probably something wront with the setup of my app (which uses babel and webpack) but I can't find what is the problem.
The webpack.config.js file has this:
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
query: {
presets: ['es2015'],
plugins: ['transform-decorators-legacy']
},
include: path.resolve('app'),
exclude: /node_modules/
},
{
test: /\.js$/,
include: path.resolve('node_modules/angular2'),
loader: 'strip-sourcemap'
}
],
noParse: [
/es6-shim/,
/reflect-metadata/,
/zone\.js(\/|\\)dist(\/|\\)zone-microtask/
]
}
Anyone has any idea?
I would see one thing that could potentially miss:
You forget to import the Http class, so the compiler couldn't resolve it:
import {Http} from 'angular2/http';
Edit
If you use ES6 only (it seems to be the case), you can use type at parameter level. To inject in this case, you need to use such approach:
#Injectable()
export class UserService {
constructor(http) {
this.http = http;
}
static get parameters() {
return [[Http]];
}
}
See these links for more details:
angular2 cannot read property 'validator' of undefined when use ngFormModel (ES6)
https://medium.com/#euphocat/angular2-router-in-es6-7-and-dependency-injection-b96944c3ba2e#.qat3cl6b4

Categories