Call Angular Component method from an imported library - javascript

Here is my Angular component:
import { basketModule } from './wind'
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
constructor(){
}
ngOnInit(){
basketModule.init()
}
public dataMain(){
alert('hi')
}
}
Here is the wind.js file which is imported above.
export var basketModule = (function () {
return {
init: function(){
dataMain()
}
}
})();
When I run the above code, it returns an error that
core.es5.js:1020 ERROR ReferenceError: dataMain is not defined
How to access the Angular component method dataMain from the imported library ?

If you're using AngularCLI, you will need to add that file to the scripts section of the angular-cli.json file.
"scripts": [
// path to script here in quotes
],
And regardless of whether you're using angular cli, make sure the 'allowJs' flag in your tsconfig.json file is set to true.
{
"compilerOptions": {
"target": "es5",
"sourceMap": true,
"allowJS": true // this one
}
}
Then try importing the library in your component
import * as wind from './path/to/lib/wind.js'
Now you should be able to access that libraries functions using the 'wind' name
wind.dataMain();

If you want an A file methode in a B file so you should import A in B
But you should put your methode in a service and then import service in wind.js

Related

How can I use a JavaScript function in a Angular TypeScript component?

I wrote a function like this:
function clean() {
fsExtra.remove(sumoDir)
}
in a file named commands.js
I export this function in this way:
module.exports = {[...], clean: clean, [...]}
I need to call this function in an Angular TypeScript component that i used for my frontend.
First of all I created a module with
ng g m home
next I import my function in home.module.ts in this way:
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import * as commands from './../../../src/commands.js'
#NgModule({
declarations: [],
imports: [
CommonModule
]
})
export class HomeModule { }
export {commands}
And I imported it in my home.component.ts
import { Component, OnInit } from '#angular/core';
import {MatCheckboxChange} from "#angular/material/checkbox";
import {commands} from "./home.module"
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
[...]
async clean(){
}
[...]
}
When I do a ng build the outpur is:
Warning: [...]/home.component.css exceeded maximum budget. Budget 2.00 kB was not met by 1.31 kB with a total of 3.31 kB.
Error: node_modules/recursive-copy/index.d.ts:1:23 - error TS2307: Cannot find module 'fs' or its corresponding type declarations.
1 import { Stats } from 'fs';
~~~~
Error: node_modules/recursive-copy/index.d.ts:2:24 - error TS7016: Could not find a declaration file for module 'stream'. '[...]node_modules/stream/index.js' implicitly has an 'any' type.
Try npm i --save-dev #types/stream if it exists or add a new declaration (.d.ts) file containing declare module 'stream';
2 import { Stream } from 'stream';
How can I fix it? or How can I import correctly my function?
Not sure what you're trying to achieve but you are trying to use the recursive-copy library in Angular while it is designed for Node.js. Angular runs in the browser and there is no API such as fs in the browser because it has no access to the machine's filesystem.

Angular: pass JSON data to child component

I have a paragraph and app component, and a JSON file:
app component:
//app.component.ts
import { Component, OnInit } from '#angular/core';
import * as data from 'JsonDataSample1.json'
#Component({
selector: 'app-root',
template: `<app-paragraph [value]='json.caseFileID'></app-paragraph>`,
})
export class AppComponent{
json = data
title = 'af-bifurcated';
}
paragraph component:
//paragraph.component.ts
import { Component, Input } from '#angular/core';
#Component({
selector: 'app-paragraph',
template: `{{ value }}`,
styleUrls: ['./paragraph.component.css']
})
export class ParagraphComponent {
#Input() value: string;
}
JSON:
{
"caseFileID": "1234567",
"pdaSubmitterEntity": "Submitter 1",
"propertyDataCollectorName": "Data Collector 1",
"propertyDataCollectorType": "APPRAISER",
"stateCredentialID": "007",
"licenseState": "CA",
"licenseExpiration": "09\/18\/2019"
}
When I try to pass the imported JSON object to the child component, nothing displays. But if instead of importing the JSON, I copy it and hardcode the value of json as equal to whatever I copy from the file, the code works. What am I doing wrong here? Why can't I pass the imported JSON?
UPDATE
I have found that in order to get the JSON file properly imported I had to add the following to my tsconfig.json:
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
...
}
To achieve expected result, use correct path jsondatasample1.json file
import * as data from './JsonDataSample1.json'
Sample working code for reference- https://stackblitz.com/edit/angular-f1hxf9?file=src/app/app.component.ts
I have found that in order to get the JSON file properly imported I had to add the following to my tsconfig.json:
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
...
}

How to include jQuery Plugin Mapael into Angular 5?

So, I tried following a bit how other questions dealt with the problem of including jQuery Plugins. But let's start with the basics first.
First, I installed the jQuery plugin.
npm i jquery
Then, I added the typescript definition.
npm install -d #types/jquery
I included it in my script array.
"apps": [{
...
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
],
...
}]
Then, I tried out if it works.
import { Component, OnInit} from '#angular/core';
import * as $ from 'jquery';
#Component({
selector: 'app-ww-inventory-map',
templateUrl: './ww-inventory-map.component.html',
styleUrls: ['./ww-inventory-map.component.scss']
})
export class WwInventoryMapComponent implements OnInit {
constructor() { }
ngOnInit() {
$(window).click(function () {
alert('ok');
});
}
}
The response came promptly...
So far, so good. First work-package is done, time to continue. I installed then the jQuery plugin mapael
npm i jquery-mapael
angular-cli.json
"apps": [{
...
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
"../node_modules/jquery-mapael/js/jquery.mapael.min.js",
"../node_modules/jquery-mousewheel/jquery.mousewheel.js"
],
...
}]
After that I tried this. Based on the code example seen on the official page
https://www.vincentbroute.fr/mapael/#basic-code-example
import { Component, OnInit } from '#angular/core';
import * as $ from 'jquery';
declare global {
interface JQuery {
mapael(map: any): JQuery;
}
}
#Component({
selector: 'app-ww-inventory-map',
templateUrl: './ww-inventory-map.component.html',
styleUrls: ['./ww-inventory-map.component.scss']
})
export class WwInventoryMapComponent implements OnInit {
constructor() { }
ngOnInit() {
$(".container").mapael({
map: {
name: "world_countries"
}
});
}
}
At first things looked fine, no warnings or problems shown, but when I load the page...
So, I'm at loss how to do this properly. I was hoping that I could fix this somehow. But none of the other few examples have been of much help to me. I apologize, knowing that there have been similar questions, but I can't really get it to work.
EDIT 1: The first solution I tried out was from Naga Sai A, but - on my end - it requires some changes, so the compiler won't complain. Thanks, Naga Sai A!
My .ts looks right this
import { Component, OnInit } from '#angular/core';
import * as $ from 'jquery';
import 'jquery-mapael';
import 'jquery-mapael/js/maps/world_countries.js';
declare global {
interface JQuery {
mapael(map: any): JQuery;
}
}
#Component({
selector: 'app-ww-inventory-map',
templateUrl: './ww-inventory-map.component.html',
styleUrls: ['./ww-inventory-map.component.scss']
})
export class WwInventoryMapComponent implements OnInit {
constructor() { }
ngOnInit() {
$(".container").mapael({
map: {
name: "world_countries"
}
});
}
}
EDIT 2: Placeholder for Peters solution
The imports are correct, but the component still require the imports. Also, including Raphael.js is NOT required. At least I didn't and the map works splendidly. My setup hasn't changed. Also, I kept my initial way of declaration.
The main issue is with your script imports. You are not importing a required dependency for Raphael. Also, you need to import any maps you plan on using. Update your angular-cli.json to the following:
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
"../node_modules/raphael/raphael.min.js",
"../node_modules/jquery-mousewheel/jquery.mousewheel.js",
"../node_modules/jquery-mapael/js/jquery.mapael.min.js",
"../node_modules/jquery-mapael/js/maps/world_countries.min.js"
],
Note from NPM:
Note on dependencies: jQuery and Raphael (and Mousewheel, if needed) must be loaded before Mapael in order to work properly.
Note on maps: map files must be loaded after Mapael in order to work properly.
https://www.npmjs.com/package/jquery-mapael#directly-in-your-page
import { Component, OnInit } from '#angular/core';
//jquery declaration
declare var $: any;
#Component({
selector: 'app-ww-inventory-map',
templateUrl: './ww-inventory-map.component.html',
styleUrls: ['./ww-inventory-map.component.scss']
})
export class WwInventoryMapComponent implements OnInit {
constructor() { }
ngOnInit() {
$(".container").mapael({
map: {
name: "world_countries"
}
});
}
}
To achieve expected result, use below option of importing jquery, jquery-mapael and js for world countries map
import * as $ from 'jquery';
import 'jquery-mapael';
import 'jquery-mapael/js/maps/world_countries.js';
and in ngOnInit
ngOnInit() {
$(".container").mapael({
map: {
name: "world_countries"
}
});
}
It works as shown in screenshot

Injection Token in Angular for Cesium.js

I'm trying to use the cesium.js library the angular way so that I can still code in typescript, I have seen some 3rd party lib tutorials, and I'm trying to inject the dependency with a dependencty token. right now, my code is not compiling, and I'm getting the error:
ERROR in ....../node_modules/cesium/Build/Cesium/Cesium.js (557,23102): Unreachable code detected.
ERROR in ....../node_modules/cesium/Build/Cesium/Cesium.js (557,24518): Unreachable code detected.
ERROR in ....../node_modules/cesium/Build/Cesium/Cesium.js (559,26990): Unreachable code detected.
I have a stack blitz with all the necessary code, but stack blitz can't handle all the dependencies to run and get the above error, so feel free to copy the code into your own environment.
my stack blitz 'demo' and here is the tutorial I followed
here are the raw files for reference as well.
This project is build with angular-cli
I started by running npm install --save cesium
cesium.lib.ts
import { InjectionToken } from '#angular/core';
import * as cesiumLib from '../../../node_modules/cesium/Build/Cesium/Cesium.js';
export const cesiumToken = new InjectionToken('cesium');
export const cesium = cesiumLib;
export type Cesium = typeof cesiumLib;
export * from 'cesium';
gobe.module.ts
import { GlobeComponent } from './globe.component';
import { CommonModule } from '#angular/common';
import { NgModule } from '#angular/core';
import * as cesiumLib from './cesium.lib';
#NgModule({
declarations: [
GlobeComponent
],
imports: [
],
providers: [
{ provide: cesiumLib.cesiumToken, useValue: cesiumLib.cesium}
]
})
export class GlobeModule {}
globe.component.ts
import { cesium, cesiumToken } from './cesium.lib';
import { Component, Inject, OnInit, ViewEncapsulation, AfterViewInit, ViewChild, ElementRef } from '#angular/core';
#Component({
selector: 'app-globe',
templateUrl: './globe.component.html',
styleUrls: ['./globe.component.css'],
encapsulation: ViewEncapsulation.None
})
export class GlobeComponent implements OnInit, AfterViewInit {
constructor( #Inject(cesiumToken) private cesium: any) {
}
ngAfterViewInit() {
this.viewer = new Cesium.viewer('cesiumContainer')
}
}
globe.component.html
<div id="cesiumContainer"></div>
globe.component.css
#import url(../Build/Cesium/Widgets/widgets.css);
#cesiumContainer {
width: 100%;
height: 720px;
margin: 0; padding: 0;
overflow: hidden;
}
tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
"allowJs": true,
"outDir": "./dist/out-tsc",
"baseUrl": "src",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/#types"
],
"lib": [
"es2016",
"dom"
]
}
}
.angular-cli.json snippet
"styles": [
"../node_modules/bootstrap/dist/css/bootstrap.min.css",
"../node_modules/bootstrap-switch/dist/css/bootstrap3/bootstrap-switch.min.css",
"styles.css",
"../node_modules/font-awesome/css/font-awesome.css",
"../node_modules/cesium/Build/Cesium/Widgets/widgets.css"
],
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
"../node_modules/bootstrap-switch/dist/js/bootstrap-switch.min.js",
"../node_modules/cesium/Build/Cesium/Cesium.js"
___UPDATE______
after making changes from #Justin Shwartzenberger
the compiler is successful but the page loads continuously until if fails... ideas? this occurs once I add the script and css to the .angular-cli.json file
In the .angular-cli.json file under the apps array first object add:
(to bring in the 3rd party css and js files needed)
"styles": [
"styles.css",
"../node_modules/cesium/Build/Cesium/Widgets/widgets.css"
],
"scripts": [
"../node_modules/cesium/Build/Cesium/Cesium.js"
],
In your cesium.lib.ts file just have:
(to create the InjectionToken only, everything else is global from that Cesium lib as it doesn't appear to be able to be imported)
import { InjectionToken } from '#angular/core';
export const cesiumToken = new InjectionToken('cesium');
In your typings.d.ts add:
(so TypeScript knows about the Cesium thing)
declare var Cesium: any;
In your app.module.ts set up:
(only need to bring in the token and then set its value to the Cesium global that the 3rd party lib creates)
import {cesiumToken} from './cesium.lib';
. . .
providers: [
{ provide: cesiumToken, useValue: Cesium }
],
. . .
And finally, in your app.component.ts:
(just need to get that token value injected into a class field and then use the API of it from there)
. . .
constructor( #Inject(cesiumToken) private cesium: any) {}
. . .
ngAfterViewInit() {
this.viewer = new this.cesium.Viewer('cesiumContainer');
}
. . .
You can go further with creating typings for the Cesium lib and encapsulating more from here, but this should get you up and working.

Angular DI in a hybrid boostrapped application

I have a sizable AngularJS (aka Angular 1) application that is written in Typescript. I've decided that new features should be written in Angular (aka Angular 4) and have taken the steps to boostrap the app in "hybrid mode".
This seems to work (all the AngularJS bits work fine) and I've added a single Angular component and that renders fine.
The problem comes when I try to add an Angular service to my Angular (so all Angular 4 so far). Angular fails to work, spitting out the seemlying ubiquitous
Can't resolve all parameters for... error.
However, if I mark the type in the components constructor with #Inject then it works ok.
All the documentation points to the fact I should not need to use #Inject routinely, so why is this failing?
My medium term need to is inject AngularJS services into the Angular components and services, and this situation isn't filling me with confidence.
app.module.ts:
// All AngualarJS definitions appear before this section.
#NgModule({
imports: [
BrowserModule,
UpgradeModule,
],
declarations: [
AppComponent,
OrgSummaryComponent
],
providers: [
OrgDetailsService,
],
bootstrap: [
AppComponent,
],
})
export class AppModule {
ngDoBootstrap() {
// Does nothing by design.
// This is to facilitate "hybrid bootstrapping"
}
}
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.body, [AppModuleName], {strictDi: true});
});
org-details.service.ts:
import {Injectable} from "#angular/core";
export class OrgDetails {
public orgName: string;
}
#Injectable()
export class OrgDetailsService {
getOrgDetails () : OrgDetails {
const od = new OrgDetails();
od.orgName = "Some Org Name from a REST service";
return od;
}
}
org-summary.component.ts:
import {Component, Inject, OnInit} from "#angular/core";
import {OrgDetailsService} from "./org-details.service";
#Component ({
selector: "orgsummary",
template: "<h2>{{OrgName}}</h2>",
})
export class OrgSummaryComponent implements OnInit {
constructor (
/*#Inject(OrgDetailsService)*/ private orgs: OrgDetailsService, // Only works if I uncomment the #Inject
) {
}
public OrgName: string;
ngOnInit(): void {
this.OrgName = `${this.orgs.getOrgDetails().orgName}`;
}
}
tsconfig.json:
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"sourceMap": true,
"noImplicitAny": true,
"declaration": true,
"experimentalDecorators": true
},
"exclude": [
"node_modules",
"**/*.spec.ts"
],
"include" : [
"app/**/*.ts"
]
}
Many thanks,
Jeff
Just add
"emitDecoratorMetadata": true
to your tsconfig.json

Categories