Using Third Party NPM packages in Angular-Cli - javascript

I have read countless tutorials on how to use third party packages but none actually say what needs to happen in the component.ts to make things work in regards to the import statement and how to get access to the function.
package: https://www.npmjs.com/package/#vote539/excel-as-json
Here are the steps I followed:
1) Npm Install excel-as-json --save
2) Add script to angluar-cli.json scripts array
3) Add typings in typings.d.ts
4) Add import statesments
1) Using Angular-Cli I installed the package
I have added this package to my scripts array inside angular-cli.json.
2) .Angular-Cli.json
...
"styles": [
"styles.scss"
],
"scripts": [ "../node_modules/excel-as-json/lib/excel-as-json.js" ],
"environmentSource": "environments/environment.ts",
"environments": {
...
3) I added in some typings
typings.d.ts
declare var module: {
id: string;
};
declare var require: any;
4) Inside my component.ts file I have added in the import statement
convertExcel = require('excel-as-json').processFile;
and then in my constructor I added in the code needed to run the conversion:
compoent.ts
export class DashboardComponent implements OnInit{
constructor() {
convertExcel('../assets/excel/assignedresources.xlsx', '../assets/excel/assignedresources.json');
}
ngOnInit() {
}
}
I tried many various of the import state, Always getting the following errors:
errors
Cannot find module 'excel-as-json'.)
(14,5): Cannot find name 'convertExcel'.)

Related

Jest ReferenceError on globally defined JS constants within Angular components

Today I've started using Jest to UnitTest some of our TypeScript files within our Angular project. After the initial Jest setup was done, creating a test for a pure TypeScript method in our util.ts was pretty straight-forward. Now I'm working on testing something in an Angular component, and I'm encountering an error because of our global constants within an imported other Component. So I'm looking for a way to either:
Give a default to these global variable in my Jest UnitTest class itself by setting them in a beforeAll.
Have a (separated) custom-jest-constants.setup.ts file to predefine all global variables for all tests
I'll save you the details of the steps I did this morning to setup and configure Jest within Angular, but I ended up with the following relevant changes because of it:
Within the angularelements/ root folder:
Added jest.config.ts:
export default {
clearMocks: true,
globalSetup: 'jest-preset-angular/global-setup',
preset: 'jest-preset-angular',
setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'],
};
Added setup-jest.ts:
import 'jest-preset-angular/setup-jest';
Added tsconfig.spec.json:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"module": "CommonJs",
"types": ["jest"]
},
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}
Modified package.json:
{
...,
"scripts": {
...,
"test": "jest"
},
"devDependencies": {
...,
"#types/jest": "^28.1.3",
"jest": "^28.1.1",
"jest-preset-angular": "^12.1.0"
}
}
Within a new test folder:
Added util.test.ts and question.component.test.ts, what they do isn't too relevant.
The error I'm getting when I run npm test:
PASS test/app/util.test.ts
FAIL test/app/questionnaire/runtime/question/question.component.test.ts
● Test suite failed to run
ReferenceError: maxFileUploadSizeInKb is not defined
42 | ...
> 43 | private static readonly UPLOAD_LIMIT_IN_BYTES = +maxFileUploadSizeInKb * 1000;
| ^
44 | private static readonly IMAGE_UPLOAD_LIMIT_IN_BYTES = +maxImageFileUploadSizeInKb * 1000;
45 | ...
at Object.<anonymous> (src/app/document-panel/document-uploading/document-uploading.component.ts:43:52)
at Object.<anonymous> (src/app/questionnaire/runtime/questionnaire-document-panel/questionnaire-document-panel.component.ts:10:1)
at Object.<anonymous> (src/app/questionnaire/runtime/question/question.component.ts:16:1)
at Object.<anonymous> (test/app/questionnaire/runtime/question/question.component.test.ts:1:1)
As for the relevant code within the document-uploading.component.ts:
declare const maxFileUploadSizeInKb: string;
declare const maxImageFileUploadSizeInKb: string;
#Component({ ... })
export class DocumentUploadingComponent extends ... {
private static readonly UPLOAD_LIMIT_IN_BYTES = +maxFileUploadSizeInKb * 1000;
private static readonly IMAGE_UPLOAD_LIMIT_IN_BYTES = +maxImageFileUploadSizeInKb * 1000;
Those declared constants are global constants that we define in our javascriptPre.jspf:
...
<script ...>
var maxFileUploadSizeInKb = '<%=Util.parseInt(SettingManager.get(Setting.maximumFileSizeInKb), Setting.DEFAULT_MAX_FILE_SIZE_KB)%>';
var maxImageFileUploadSizeInKb = '<%=Util.parseInt(SettingManager.get(Setting.maximumImageFileSizeInKb), Setting.DEFAULT_MAX_IMAGE_FILE_SIZE_KB)%>';
</script>
...
Which will basically inject the settings we've defined in our Java backend to this globally defined JS variable, which is accessible within our Angular/Typescript classes as can be seen in the document-uploading.component.ts.
If I temporarily modify the DocumentUploadingComponent to hard-coded constants like this:
private static readonly UPLOAD_LIMIT_IN_BYTES = 5_000_000;
private static readonly IMAGE_UPLOAD_LIMIT_IN_BYTES = 400_000;
Everything works as intended when I run npm test.
So, back to the original question: how could I overwrite/setup the maxFileUploadSizeInKb/maxImageFileUploadSizeInKb to some default value, either within a custom Jest setup file or in a beforeAll within my UnitTest file (or elsewhere perhaps)?
Right after I posted my answer above I finally found the solution, which was simpler than I thought.
In jest.config.ts I've added:
setupFiles: ['<rootDir>/custom-jest-setup.ts'],
And in that added new custom-jest-setup.ts file within my angularelements/ folder I've used:
// #ts-ignore
global.maxFileUploadSizeInKb = 5000;
// #ts-ignore
global.maxImageFileUploadSizeInKb = 400;
And that's it. My UnitTests run without any issues now!

Upgrading to Angular 10 - Fix CommonJS or AMD dependencies can cause optimization bailouts

I am trying to upgrade my Angular 9 app to Angular 10 version, but I am getting the below warning after the upgrade
rxjs\BehaviorSubject.js depends on rxjs-compat/BehaviorSubject
How can I fix this?
When you use a dependency that is packaged with CommonJS, it can result in larger slower applications
Starting with version 10, Angular now warns you when your build pulls in one of these bundles. If you’ve started seeing these warnings for your dependencies, let your dependency know that you’d prefer an ECMAScript module (ESM) bundle.
Here is an official documentation - Configuring CommonJS dependencies
In your angular.json file look for the build object and add
allowedCommonJsDependencies
as shown below -
"build": {
"builder": "#angular-devkit/build-angular:browser",
"options": {
"allowedCommonJsDependencies": [
"rxjs-compat",
... few more commonjs dependencies ...
]
...
}
...
},
Try replacing the rxjs imports rxjs/internal/operators with rxjs/operators.
Example:
import { catchError, retry } from 'rxjs/internal/operators';
with
import { catchError, retry } from 'rxjs/operators';
It is recommended that you avoid depending on CommonJS modules in your Angular applications. Depending on the CommonJS modules, they can prevent bundlers and minifiers from optimizing your application, which results in larger bundle sizes. Instead, it is recommended that you use ECMAScript modules in your entire application.
Still, if you don't care about your bundling size, to disable these warnings, you can add the CommonJS module name to allowedCommonJsDependencies option in the build options located in the angular.json file.
"build": {
"builder": "#angular-devkit/build-angular:browser",
"options": {
"allowedCommonJsDependencies": [
"rxjs-compat"
]
...
}
...
},
Source
For the RXJS library you can do the following changes.
For imports, such as 'rxjs/internal/<anything>' and 'rxjs/index', replace it with just 'rxjs'.
For imports such as 'rxjs/internal/operators', replace it with 'rxjs/operators'.
Or replace just rxjs.
Just change the import:
from:
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
To:
import { BehaviorSubject } from 'rxjs';
Another case of this is the problem being warned about during the build with the use of BehaviorSubject from rxjs when using the following style of imports:
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
It results in the following error:
Warning: my.service.ts depends on 'rxjs/BehaviorSubject'. CommonJS or
AMD dependencies can cause optimization bailouts.
By importing from the root module instead, the warning is no longer present during the build:
import { BehaviorSubject } from 'rxjs';
In my case (after update to TypeScript version 3.9.7) flatMap is deprecated (from rxjs/operators).
This is alias for mergeMap, so just I replaced:
import { flatMap } from 'rxjs/internal/operators';
to
import { mergeMap } from 'rxjs/operators';
I had a similar issue (app.module.ts depends on 'ngx-google-places-autocomplete'), but many answers did not help me.
So if you have x depends on y, just add y in the angular.json file in "allowedCommonJsDependencies".
to fix this issue on terminal
in angular.json put this line in :
"architect": {
"build": {
"builder": "#angular-devkit/build-angular:browser",
"options": {
"allowedCommonJsDependencies": [
"rxjs",
],
I have a very big project with deprecated imports 'rxjs' and create this script for upgrading all deprecated imports:
python3.6 replace_imports.py PATH_TO_SRC_DIR
This script upgrades the import like "rxjs\/(internal|Observable|Subject|ReplaySubject|Subscription|BehaviorSubject)"
to
import { * } from rxjs
Also try to upgrade rxjs-compat.

Property '' does not exist on type 'Request<ParamsDictionary>'

When trying to extend the Request interface from the package express to add some custom properties, I'm getting the following typescript error:
TS2339: Property '' does not exist on type 'Request<ParamsDictionary>'.
Do you know how to solve that?
Since a recent update of its typings and dependencies, I found that the following should fix the errors in your application.
In your tsconfig.json
{
"compilerOptions": {
//...
"typeRoots": [
"./custom_typings",
"./node_modules/#types"
],
}
// ...
}
And in your custom typings
// custom_typings/express/index.d.ts
declare namespace Express {
interface Request {
customProperties: string[];
}
}
Just add the following, what this does is it simply adds a custom property to the express Request interface
declare global {
namespace Express {
interface Request {
propertyName: string; //or can be anythin
}
}
}
I recently had the same issue, I followed the solution in the previous comments and this repo and I still had the same issue. After doing more digging it seems like it's a bug with ts-node.
To solve this you need to run your server with a --files flag
So if you normally run your server
ts-node ./src/server.ts or nodemon ./src/server.ts
Change it to
ts-node --files ./src/server.ts or nodemon --files ./src/server.ts
After that, I was able to get rid of both the VScode errors and errors while starting the server.
In my case it was missing types for express. What I'm currently working on is migrating our codebase from Yarn to PNPM. The difference with PNPM is it doesn't hoist dependencies the way Yarn does so I had to add the dependencies on the package.json for each workspace that would use that dependency.
This is the error I encountered:
TSError: ⨯ Unable to compile TypeScript:
../server/src/api/filters/googleFilter.ts:6:23 - error TS2339: Property 'headers' does not exist on type 'Request<core.ParamsDictionary>'.
6 const idToken = req.headers.authorization;
It took me quite a few searches to look for a fix when I decided to open up the node_modules folder of that workspace. Inside node_modules/#types/express/index.d.ts
/// <reference types="express-serve-static-core" />
/// <reference types="serve-static" />
import * as bodyParser from "body-parser";
import serveStatic = require("serve-static");
import * as core from "express-serve-static-core";
import * as qs from "qs";
I saw my IDE showing errors telling me that it cannot find the types for express-serve-static-core and serve-static so what I did was to add it on the package.json of that workspace and that fixed the errors on the terminal.
Hope this helps someone else who will encounter the same issue with PNPM.
This worked for me!
Using ts-node
Add the following file to add a property to the express Request interface as suggested by #Rishav Sinha
Add this file src/types/types.custom.d.ts
declare global {
declare namespace Express {
interface Request {
user?: any,
page?: number,
}
}
}
// If this file has no import/export statements (i.e. is a script)
// convert it into a module by adding an empty export statement.
export { }
Add in tsconfig.json
{
"compilerOptions": {
//...
"typeRoots": [
"./types",
"./node_modules/#types"
],
}
// ...
}
Run this command with --files options as suggested by #Shahar Sharron
If you installed globally ts-node
$ ts-node --files ./src/index.ts
or to run from your project dependencies ts-node
$ npx ts-node --files ./src/index.ts
Using nodemon
If you want to use nodemom
Add this file in folder project nodemon.json
{
"watch": ["src/**/*.ts"],
"ext": "ts,json",
"ignore": [
"src/**/*.spec.ts",
"src/**/*.test.ts"
],
"exec": "npx ts-node --files ./src/index.ts"
}
Run nodemon
$ nodemon

How to use JQuery functions in Angular 5?

I want to use titl.js in my Angular 5 app. Here is what I did so far:
npm install jquery --save
npm install tilt.js --save
And then in my .angular-cli.json
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
"../node_modules/tilt.js/dest/tilt.jquery.min.js"
]
In the component which uses tilt.js I have:
declare var jQuery: any;
And
#ViewChild( 'LoginTitl' ) login_titl: ElementRef;
ngAfterViewInit() {
jQuery( this.login_titl.nativeElement ).tilt( {
scale: 1.1
} );
}
But I get the following error:
Property 'tilt' does not exist on type 'JQuery<any>'.
Just working now.
I don't know if this is the solution or not, but adding the following line made the code work.
import 'tilt.js';

How can I organize my Angular app folders like a Java package?

How to organize Angular 2 app folder structure like Java packages?
Consider the following project layout:
app
|_model
|_component
|_service
I would like to import foo.service.ts from service to bar.component.ts in component. But as far as I know, Angular 2 import supports only relative paths like /../service/, which seems very clunky solution.
Is there a way to refer folders with absolute bath from root folder, like with Java packages?
UPDATE 2016-06-01
using npm install typescript#next you can already use this function
I assume that your tree looks like this:
node_modules
|_#angular
|_rxjs
app
|_model
|_component
|_service
package.json
tsconfig.json
You should add in your tsconfig.json the following lines:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"*": [
"app/*",
"node_modules/*"
]
}
}
}
then you can reference your modules like you do with regular #angular/rxjs modules
import { MyService } from 'service/MyService';
import { Component } from '#angular/core';
import { Observable } from 'rxjs';
Note: webpack needs also the following lines in webpack.config.js
resolve: {
modulesDirectories: [
'node_modules',
'app'
]
}
Not yet, it should be present soon with Typescript 2.0
Look here
https://github.com/Microsoft/TypeScript/issues/5039

Categories

Resources