Including custom typings in JHipster (v5.82) project - javascript

The basic idea is to start with a new JHipster project (v5.8.2) and integrate the Metronic Angular theme in it.
I haven't found much in the way of documentation for this task, but sluggishly I've integrated the various css/js bundles, the components, however I ran across a problem with some of their directives.
So basically in toggle.directive.ts after the view initiates it tries to create a new KTToggle see
ngAfterViewInit(): void {
this.toggle = new KTToggle(this.el.nativeElement, this.options);
}
KTToggle is defined in scripts.bundle.js that I've already imported in vendor.ts.
I've also copied typings.d.ts file from metronic in src/main/webapp/app.
The problem is that it doesn't find KTToggle, when running npm run webpack:build I get no error, but when actually trying to access the page I get
ERROR ReferenceError: "KTToggle is not defined"
Additionally in IntelliJ I get the following error
TS2350: Only a void function can be called with the 'new' keyword
I tried to declare KTToggle straight in the directive
declare var KTToggle: any;
But this give me the same ReferenceError.
Also in tsconfig.json I tried to point to the typings file through typeRoots, types, files all gave me either the same error or for types caused other parts of the app to fail.
I'm not too experienced with Angular/Webpack but I suspect the typing is not properly loaded, because if I try to go to the definition of KTToggle in IntelliJ it points me to the scripts.bundle.js file.
I welcome any kind of help, thank you.
Additional info:
typings.d.ts
/* SystemJS module definition */
declare var module: NodeModule;
interface NodeModule {
id: string;
}
declare var KTMenu: any;
declare var KTOffcanvas: any;
declare var KTScrolltop: any;
declare var KTHeader: any;
declare var KTToggle: any;
declare var KTUtil: any;
declare var KTPortlet: any;
declare var KTDialog: any;
declare var Chart: any;
scripts.bundle.js
.....
KTToggle=function(t,e){var n=this,i=KTUtil.get(t);KTUtil.get("body");if(i){var o={togglerState:"",targetState:""}
....
L.E. 2020-04-11
What we ended up doing was setting a new entry point in the the webpack configuration file (both dev and prod), like this:
entry: {
global: './src/main/webapp/content/scss/global.scss',
main: './src/main/webapp/app/app.main',
// metronic scripts bundled, contains needed JS for Metronic functionalities
metronicScripts: [
'./src/main/webapp/content/metronic/assets/demo/default/base/scripts.bundle.js'
]
},
and then in the common webpack configuration we modified the HtmlWebpackPlugin to include the new chunk like so:
new HtmlWebpackPlugin({
template: './src/main/webapp/index.html',
chunks: [
// include metronic bundle before the main bundle so that we can utilize metronic variables in components and initialize the layout for example
'metronicScripts'
,'polyfills'
,'main'
,'global'
],
chunksSortMode: 'manual',
inject: 'body'
}),
Afterwards we could use the various elements from metronic inside components like so
...
declar var KTUtil: any;
#Component({...})
...
ngOnInit() {
KTUtil.init();
}

(ERROR ReferenceError: "KTToggle is not defined") mean you not load the script file toggle.js,
So make sure you load all what Metronic loaded in index.html file and not delete imports of it, by default Metronic load this files in index.html :
<script src="assets/js/global/components/base/util.js" type="application/javascript"></script>
<script src="assets/js/global/components/base/header.js" type="application/javascript"></script>
<script src="assets/js/global/components/base/menu.js" type="application/javascript"></script>
<script src="assets/js/global/components/base/offcanvas.js" type="application/javascript"></script>
<script src="assets/js/global/components/base/scrolltop.js" type="application/javascript"></script>
<script src="assets/js/global/components/base/toggle.js" type="application/javascript"></script>
<script src="assets/js/global/components/base/dialog.js" type="application/javascript"></script>
<script src="assets/js/global/components/base/wizard.js" type="application/javascript"></script>

For someone stumbling upon this question, looking for answers, adding the reference to bundled files in angular.json file, resolved the issue for me.
"architect": {
"build": {
...
"options": {
....
"scripts": [
"src/assets/vendors/global/vendors.bundle.js",
"src/assets/js/demo1/scripts.bundle.js"
],
..
}
..
}

Related

Global styles for StencilJs custom web component not recognized in Angular app

I've used Stencil to create a custom web component.
I've set a bunch of CSS variables in /src/global/global.scss:
E.g.:
:root {
--font-family: 'Roboto Condensed';
--font-size: 1.75rem;
... etc ...
}
My stencil.config.ts looks like this:
export const config: Config = {
namespace: 'my-component',
globalStyle: 'src/global/global.scss',
outputTargets: [
{
type: 'dist',
esmLoaderPath: '../loader',
},
{
type: 'dist-custom-elements-bundle',
}
],
};
If I publish the component to NPM, then install it into my Angular app, it works, except that it doesn't recognize any of the variables defined in the global CSS file.
In my Angular project - the file is here, and does contain the variables:
/node_modules/my-component/dist/my-component/my-component.css
It's just that my Angular project doesn't seem to be aware of that file.
I've read elsewhere that I should include this line in the index.html file of my Angular project:
<link rel="stylesheet" href="/dist/my-component/my-component.css">
However, I've tried that, by when I run ng serve, the browser doesn't find:
http://localhost:4200/dist/my-component/my-component.css
I'm guessing that I'm missing some configuration setting that tells Angular to copy the CSS file from /node_modules/my-component/dist/my-component/my-component.css to dist/my-component/my-component.css, but I don't know how or where to do that.
in angular.json:
"styles": [
"./node_modules/my-component/dist/my-component/my-component.css",
"src/styles.scss"
],

Instantclick is not defined on Rails 6

I try to integrate instantclick to my rails 6 application. I added the instantclick.js file in my javascript/custom folder. Then, I import it in javascript/packs/application.js:
require("custom/instantclick")
I added to the end of the body tag of my layout the following line to initialize instantclick:
...
<script data-no-instant>InstantClick.init();</script>
</body>
</html>
Then, I get the following error in console:
(index):404 Uncaught ReferenceError: InstantClick is not defined
I'm new to using webpacker, maybe I did something wrong. However, the instantclick.js file is imported. Any idea what I'm doing wrong? Thanks.
Webpack works differently than Sprockets. One thing you're running into is that webpack does not expose anything to the global scope. That means calling functions from a script tag won't work as expected unless you instruct webpack to add those variables to the window object.
Your instantclick.js file is also not module-aware, i.e, it does not export anything, such as with module.exports = InstantClick.
With webpack though, you can configure it to do both. You'll need to both export and expose InstantClick:
yarn add expose-loader exports-loader
// config/webpack/environment.js
const { environment } = require('#rails/webpacker')
environment.loaders.append('InstantClick', {
test: /instantclick/,
use: [{
loader: 'expose-loader',
options: 'InstantClick'
},
{
loader: 'exports-loader',
options: 'InstantClick'
}]
})
module.exports = environment
There is more to learn and other ways you can do it of course. Here are some resources:
https://webpack.js.org/guides/shimming/
http://www.matthiassommer.it/programming/expose-global-variables-methods-modules-javascript/
https://rossta.net/blog/three-ways-webpack-surprises-rails-developers.html

How to inject Webpack DefinePlugin variables in non Module Scripts

I have the following issue:
I'm using the DefinePlugin to define some variables across .js modules. This is working fine in .js modules
However, my multi page application loads a local script (custom.js) inside a <HEADER> TAG. This script is standard javascript (not a module), using one of the variables defined in DefinePlugin. It's a .js that must be loaded in every page of the App.
For some reason this variable WEB_CONTEXT is not being interpolated by Webpack on BUILD process.
I assume that the reason is that as it is not recognized as a dependency.
Webpack config.js:
new webpack.DefinePlugin({
'WEB_CONTEXT': 'myapp/main'
);
The global script is loaded like this:
<script src="./src/js/custom.js"></script>
custom.js
$(function () {
// Compiled file incorrectly shows:
const myPath = `${WEB_CONTEXT}/resources/images`;
// Instead of:
const myPath = `myapp/main/resources/images`;
});
});
Question is:
Is there anyway with Webpack to make WEB_CONTEXT variable available ALSO for those scripts like custom.js (not imported, but loaded via ?
Webpack "works" only on files that are part of the dependency tree that starts from the entry file.
If your custom.js file is not inside this tree, webpack won't touch it.
You can add it by require it, or add it as additional entry to your app.
//webpack.config.js
module.exports = {
entry: {
main: './path/to/my/entry/file.js',
custom: './path/to/custom.js'
}
};
webpack.config.js
entry : {
main: './path/to/my/entry/file.js',
custom: './path/to/custom.js'
}
And the in the plugins section:
new HtmlWebpackPlugin({
template: `./${ruta}`,
inject: true,
chunks: ['main', 'custom'], // <-Added custom chunk here.
filename: `${fileName}.html`,
templateParameters: {
WEB_CONTEXT: basePath
}
});

TypeError: Class extends value undefined is not a constructor or null

This problem has been causing me to lose my sanity for the last couple of days.
Here is my directory structure:
[src]
|- cmds/
| |- Gh.js
| \- Help.js
|- commands.js
|...
I am trying to import a class exported by commands.js into Help.js and Gh.js (and any other files I might add in the future). However, I keep getting an error:
class Gh extends _commands.Command {
^
TypeError: Class extends value undefined is not a constructor or null
All of the files are being transpiled using Babel, with env set to "node": "current" and using the wildcard package. I have tried to set it for "browser" to see if it was an issue of it being too "advanced", but I got a different error about super functions (or something), which I assume is the same issue.
Here is the class being exported from commands.js:
export class Command {
constructor (msg) {
this.id = msg.author.id
this.msg = msg
}
action () {}
get data () {
return readData().user[this.id]
}
updateUserData (key, val) {
updateUserData(this.id, key, val)
}
sendMsg (data) {
sendMsg(this.msg, data)
}
}
...and here is cmds/Gh.js, one of the files that I am trying to import Command into:
import {Command} from '../commands'
export class Gh extends Command {
constructor (msg) {
super(msg)
this.desc = 'Returns GitHub repository link and exits'
}
action () {
this.sendMsg('GitHub link: https://github.com/owm111/knife-wife')
}
}
I tried putting Command into both of the cmds/, and they worked perfectly. However, when moving it back into commands.js, it broke again. I tried changing the path it is importing from from ../commands to ./../commands, ../commands.js, ./../commands.js; none worked. I moving commands.js into cmds/, still broke. I tried to console.log(Command) in both of the cmds/, but they both returned undefined.
All of this makes it look like is a problem with importing, but I cannot figure out what for the life of me. Please help.
If anyone else sees this error, the first thing to look for is circular dependencies. Import file A into B, B into some other file C, and so on. If any of C through Z is imported into A, then JS will not be able to ensure that a file is defined at the time that another file needs it (and will not try to go back and fill in the blanks later).
This was likely the case here, since there was clearly other code not posted, and it only appeared when file dependencies were introduced. The problem exists regardless of file structure: the only structure guaranteed to avoid it is a single giant JS file. The solution is to ensure a strict tree structure of relationships between classes, and use factory methods or alternative communications like emitters to keep the couplings loose.
If you have more than a couple import / require statements, I recommend periodically running a checker like Madge to find and optionally visualize any loops before they become hard to undo.
npm install --save-dev madge
node_modules/madge/bin/cli.js --warning --circular --extensions js ./
As others have mentioned, this results from circular dependencies. I tried for hours to resolve it. Ultimately it was a tool called dpdm that worked wonders for me, finding 27 cycles and quickly leading to resolution. (I only had to solve a couple of those before the rest resolved as well.)
yarn global add dpdm or npm i -g dpdm
Then
dpdm file.js or dpdm file.ts
In my case this found a large number of cycles that Madge and manual inspection had failed to reveal. Great tool.
This is just a simple fix for node.js. Remove export from your class and at the bottom of your file put this in it.
module.exports.Command;
Now if you want to use the command class anywhere you just need to put this in each file where you would like to use it.
var { Command } = require('Command.js');
In my case, I made the dumb mistake of putting parentheses after extending React.Component like this:
class Classname extend React.Component() {
...
Removing the parentheses fixed the error.
In my case: I was importing a non-existing class:
Counter.js:
import React, { Compontent } from 'react';
class Counter extends Compontent {
App.js:
import React from 'react';
import Counter from './components/Counter';
function App() {
Another cause can be that you use the following syntax (after copying a class from a declaration file (xxxx.d.ts) -> xxxx.ts
export declare abstract class Something {
should be (of course):
export abstract class Something {
In my case, the order of the export dependency order was wrong. The dependency was in inheritance. I was using index.ts to export class, interfaces, abstract classes.
If B extends A, and on your index.ts you did the following, this will through the error mentioning A.
export { B } from 'somewhere';
export { A } from 'somewhere';
To fix that, you must maintain the order of dependencies like
export { A } from 'somewhere';
export { B } from 'somewhere';
This is an issue with your node version
What i did was to uninstall my node version manager, re installed and used it to install all my node versions , did nvm use to select which one to use , in my case it was 14.17.3 ,
ran npx react-native init command
That fixed it for me
I got this error that "Sequelize TypeError: Class extends value undefined is not a constructor or null, NodeJS" and solved it using that. If you have the same error, you can use the following solution that I've tried to explain it in code.
for example:
module.exports = (sequelize, DataTypes) => {
// Modeling a table: Inheritance
class Todo extends sequelize.Model {} // (!) Error
// if you want to use the above line, add the following line to "lib\sequelize.js file
// Sequelize.prototype.Model = Model; // add this line here
class Example extends sequelize.Sequelize.Model { }
Example.init({
title: DataTypes.STRING,
description: DataTypes.STRING,
status: DataTypes.BOOLEAN
}, {
sequelize,
modelName: 'todo',
timestamps: true
});
return Example;
};
For people getting this error when using JSweet java to javascript transpiler, I was able to fix it by enabling the 'bundle' option, mentioned here:
Bundle up all the generated code in a single file, which can be used
in the browser. The bundle files are called 'bundle.ts',
'bundle.d.ts', or 'bundle.js' depending on the kind of generated code.
NOTE: bundles are not compatible with any module kind other than
'none'.
This is part of my POM which contains the 'bundle true' addition:
<plugin>
<groupId>org.jsweet</groupId>
<artifactId>jsweet-maven-plugin</artifactId>
<version>${jsweet.transpiler.version}</version>
<configuration>
<verbose>true</verbose>
<tsOut>target/ts</tsOut>
<outDir>target/js</outDir>
<candiesJsOut>webapp</candiesJsOut>
<targetVersion>ES6</targetVersion>
<module>none</module>
<moduleResolution>classic</moduleResolution>
<bundle>true</bundle>
</configuration>
<executions>
<execution>
<id>generate-js</id>
<phase>generate-sources</phase>
<goals>
<goal>jsweet</goal>
</goals>
</execution>
</executions>
</plugin>
Then re-run 'mvn generate-sources', and make sure that you change the index.html file to load the new bundle.js file:
<html>
<head>
<link rel="icon" type="image/png" href="logo.png">
<link rel="shortcut icon" href="logo.png">
<meta charset="utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
</head>
<body>
<p>Test page</p>
<p id="target"></p>
<script type="text/javascript" src="../webapp/j4ts-0.7.0-SNAPSHOT/bundle.js"></script>
<script type="text/javascript" src="../target/js/bundle.js"></script>
</body>
</html>
I got this error on Angular "class extends value undefined is not a constructor or null" when running cypress and resolved it by changing the compiler options is tsconfig.json.
from:
"compilerOptions": {
"baseUrl": "./",
"downlevelIteration": true,
"resolveJsonModule": true,
"paths": {
"*": [
"./node_modules/*" <== throws error
],
to:
"compilerOptions": {
"baseUrl": "./",
"downlevelIteration": true,
"resolveJsonModule": true,
"paths": {
"*": [
"./node_modules/" <== correct
],
Another common cause of this error is if you installed Node.js into an already existing folding of an older installation of Node.js. Removing and reinstalling Node.js fixes that issue.
I got this error when I upgraded to Angular 13 from 12. ng update did not update webpack to v5 and their upgrade checklist doesn't mention it being a retirement. Once I upgraded webpack to latest, the error went away for me.
Anyone is facing this issue even though there is no circular dependency and using webpack then please add target:node in your webpack config file.

How to change Ember.js location from where it serves the static assets

I am a beginner at Ember.js, so sorry if this is an easy question, but I couldn't locate the answer.
Basically, after running ember build, Ember's index.html will have these links for the built .js files:
<script src="assets/vendor-4d126b4b021a3ad999a0115386f5edf4.js" integrity=""></script>
<script src="assets/bsrs-ember-1906440e1018cb4d5bdbe009ff42b763.js" integrity=""></script>
I'd like to change these links in index.html to:
<script src="/static/assets/vendor-4d126b4b021a3ad999a0115386f5edf4.js" integrity=""></script>
<script src="/static/assets/bsrs-ember-1906440e1018cb4d5bdbe009ff42b763.js" integrity=""></script>
Is this possible? If so, how do you do this?
You need to alter the ember-cli-build file (previously called the Brocfile) to ensure a special prefix gets added to the front of your assets (note: only done for production builds)
var app = new EmberApp({
fingerprint: {
prepend: '/static/'
}
});
For changing path of vendor.js you can pass app.outputPaths.vendor.js property to EmberApp in ember-cli-build.js:
var app = new EmberApp({
outputPaths: {
vendor: {
js: '/static/assets/vendor.js'
}
}
});

Categories

Resources