Injection Token in Angular for Cesium.js - javascript

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.

Related

Angular 7 Creating dynamic modules with compileModuleAndAllComponentsAsync aot build issue

Problem :
I have to render a dynamic html which generates at run-time as a string, so for that purpose I've used dynamic components approach as innerHTML just not cater angular attributues like *ngIf, formGroup, router-link etc, but getting following error after deploying on local server.
Error :
Error: Unexpected value 'function(){}' imported by the module 'function(){}'. Please add a #NgModule annotation.
I tried creating the dynamic module but was getting error when making aot build because it was inside a non lazy-loaded module and according to a solution I found that aot will not work for dynamic components generating in a lazy-loaded module.
Now when I have moved it in a non lazy-loaded module I am not getting any error locally when generating aot build but getting this error after deployment however deployment is successful and nothing is breaking there.
DYNAMIC MODULE
export function createCompiler(compilerFactory: CompilerFactory) {
return compilerFactory.createCompiler();
}
#NgModule({
declarations: [StepComponent],
imports: [
CommonModule
],
exports: [StepComponent],
entryComponents: [StepComponent],
providers: [
{ provide: COMPILER_OPTIONS, useValue: {}, multi: true },
{ provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] },
{ provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] }
]
})
export class DynamicStepModule { }
STEP COMPONENT
export class StepComponent implements OnInit, OnChanges {
#Input() step: Steps;
#ViewChild('dynamicComponent', { read: ViewContainerRef }) container: ViewContainerRef;
constructor(private compiler: Compiler) { }
ngOnInit() { }
ngOnChanges(change: SimpleChanges) {
if (this.step && change.step.currentValue !== change.step.previousValue) {
this.addComponent(this.step);
}
}
addComponent(step: Steps) {
const cmp = Component({ template: step.formattedText })(class DynamicComponent {
stepFormGroup: FormGroup;
constructor(
) {
// Some Component related code
}
});
const meta = NgModule({
imports: [
CommonModule,
FormsModule,
MaterialModule,
ReactiveFormsModule,
LibSharedModule,
BrowserModule,
BrowserAnimationsModule
],
declarations: [cmp]
})(class DynamicModule {
});
this.compiler
.compileModuleAndAllComponentsAsync(meta)
.then(factories => {
const factory = factories.componentFactories.find(component => component.componentType === cmp);
this.container.remove();
this.container.createComponent(factory);
});
}
}
Locally when generating aot build not getting error but after deploying on a local server getting this issue:
ERROR Error: Unexpected value 'function(){}' imported by the module 'function(){}'. Please add a #NgModule annotation.

Angular7 in production mode: Uncaught ReferenceError: environment is not defined

My application works fine in development, and ng build --prod --source-map builds application successfully. But when I try to access it in the browser, I get this error:
app.module.ts:47 Uncaught ReferenceError: env is not defined
at Object.zUnb (app.module.ts:47)
at u (bootstrap:81)
Here is my app.module.ts file (relevant part):
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { APP_BASE_HREF } from '#angular/common';
import { HTTP_INTERCEPTORS, HttpClient } from '#angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { environment as env } from '#env/environment'; // <- import env
import { CoreModule } from '#app/core/core.module';
#NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
BrowserAnimationsModule,
MatSidenavModule,
CoreModule,
AppRoutingModule,
],
providers: [
{ provide: APP_BASE_HREF, useValue: env.baseHref } // <--- error
],
bootstrap: [AppComponent]
})
export class AppModule {}
And this is my tsconfig.json file where #env path is defined:
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./src/",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/#types"
],
"lib": [
"es2017",
"dom"
],
"paths": {
"#app/*": ["app/*"],
"#env/*": ["environments/*"]
}
}
}
I upgraded #angular-devkit/build-angular from version ~0.6.0 to ^0.13.3 and it solved the problem.
import { environment } as env from '#env/environment';
this should do the trick...

Call Angular Component method from an imported library

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

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

Error trying to do an hybrid AngularJS/Angular app

Im trying to do an hybrid app using AngularJS & Angular(2).
I already have a big AngularJS app and I just want to use a component from an Angular app.
Using https://angular.io/docs/ts/latest/guide/upgrade.html, I have created two new files
app.module.ts
import { UpgradeModule } from '#angular/upgrade/static';
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
#NgModule({
imports: [
BrowserModule,
UpgradeModule,
],
})
export class AppModule {
ngDoBootstrap() {}
}
and main.ts
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { UpgradeModule } from '#angular/upgrade/static';
import { AppModule } from './app.module';
import App from './app.js';
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.documentElement, [App]);
});
and I have deleted the old bootstrap.js file
import angular from 'angular';
import App from './app';
angular.element(function() {
angular.bootstrap(document, [App], { strictDi: true });
});
The entry of my webpack build is now main.ts.
When I start my app, I have ana issue :
ERROR in ./client/app/main.ts
Module not found: Error: Can't resolve './app.module' in '/home/bsousa/Projects/S6/client/app'
# ./client/app/main.ts 5:21-44
Do someone know why ?
Here is the tsconfig.json, maybe it can help
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"allowJs": true,
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false,
"allowUnreachableCode": true
},
"exclude": [
"node_modules"
]
}
Files structure
/
client
app
...
app.js
app.module.ts
main.ts
gulpfile.js
webpack.config.js
Well I don't know why the import did not work but when I set everything in the main.ts file, it works
import 'zone.js';
import 'angular';
import App from './app.js';
import { NgModule } from '#angular/core';
import { UpgradeModule } from '#angular/upgrade/static';
import { BrowserModule } from '#angular/platform-browser';
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
#NgModule({
imports: [
BrowserModule,
UpgradeModule,
],
})
export class AppModule {
ngDoBootstrap() {
}
}
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.documentElement, [App.name], { strictDi: true });
});
My AngularJS is bootstrapped with Angular.
Now I'm trying to import my Angular app into my project as a node package but I think I have to do some improvements with the export.
I would like to import the root component, do I have to import the root module as well ?

Categories