How can I make Cesium, SystemJS, and Angular2 compatible with each other?

Could anyone provide a working example of using SystemJS (not Webpack) with Angular2 (in TypeScript, not Dart) and Cesium (npm)?

I came across a blog post on cesiumjs' site that discusses this:

The author mentioned, "You can't simply do a require('cesium')." However, the article focuses on the Webpack way which I don't have access to.

I am encountering this error in the browser:

Error: (SystemJS) AMD module http://localhost:3000/node_modules/cesium/Build/CesiumUnminified/Cesium.js did not define

This is what my systemjs.config.js file looks like:

paths: {'npm:' :  'node_modules/'},
map: {
    app: 'dist',
    '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
    ...
    'require': 'npm:requirejs/require.js',
    'cesium': 'npm:cesium/Build/CesiumUnminified/Cesium.js',
    ...
}

Example of using @Injectable():

let Cesium = require('cesium');
import { Injectable } from '@angular/core';

@Injectable()

export class CesiumClock {
    private _start:any = Cesium.JulianDate.now();
    private _stop:any = Cesium.JulianDate.addHours(this._start,12,new Cesium.JulianDate());
    private _clock:any = new Cesium.Clock({
        startTime: this._start,
        stopTime: this._stop,
        currentTime: this._start,
        clockRange: Cesium.ClockRange.LOOP_STOP,
        mutliplier: 1,
        shouldAnimate: true
    });
}

And here's the client code that attempts to use my 'CesiumClock', resulting in an error in the browser after transpiling:

import { Component } from '@angular/core';
import { CesiumClock } from '../services/index';

@Component({
    moduleId: module.id.replace("/dist", "/app"),
    templateUrl: 'stuff.component.html',
    styleUrls: [
        'stuff.css',
        'node_modules/cesium/Build/Cesium/Widgets/widgets.css'
    ]
 })

export class StuffComponent {
    constructor(private _cesiumClock:CesiumClock) {}
}

UPDATE:

Thanks to @artem's input, I managed to resolve the specific 'Error: (SystemJS) AMD' issue in the browser. However, now when trying to utilize anything related to Cesium, such as new Cesium.Viewer(...), the Cesium object appears empty leading to the error

Cesium.Viewer is not a constructor

Answer №1

Big shoutout to @artem for shedding light on this issue. Here's the final solution that really worked for me:

systemjs.config.js (Check out 'cesium' under packages and take note of the global variable, CESIUM_BASE_URL)

(function(global){
    global.CESIUM_BASE_URL = './node_modules/cesium/Build/CesiumUnminified';
    System.config({
        paths: {
            // aliases for paths
            'npm:': 'node_modules/'
        },
        map: {
            ...
            // aliases for paths
            'cesium': 'npm:cesium/Build/CesiumUnminified'
            ...
        },
        packages: {
            ...
            'cesium': {
                main: './Cesium.js',
                meta: {
                    '*.js': {
                        format: 'cjs'
                    }
                }
            },
            ...
        }
    });
})(this);

cesium.viewer.ts (Note how declare and import are combined. The declare statement lets the TypeScript compiler recognize Cesium, while the import ensures it works in the browser.)

declare var Cesium:any;
import 'cesium';

@Injectable()
export class CesiumViewer {
    ...
    this._viewer = new Cesium.Viewer(elem, {...});
    ...
}

I think the meta section is crucial because Cesium requires multiple .js files. Without the meta *.js property, only Cesium.js is fetched, which isn't sufficient, whether minified or not, sourced or not.

Now that the JavaScript part is sorted, I'm facing a major CSS crisis - the Cesium map looks like a complete mess in the browser.

Answer №2

SystemJS automatically detects the format for CesiumUnminified/Cesium.js as amd, but strangely it does not function properly as an amd module with SystemJS. However, it can be successfully loaded if you adjust its format to CommonJS:

    map: {
         ...
        'cesium': 'npm:cesium/Build/CesiumUnminified',

and

    packages: {
            ...
        cesium: {
            main: 'Cesium.js',
            format: 'cjs'
        },

Update: It seems that SystemJS struggles to utilize both versions provided in node_modules/cesium/Build: specifying either mapping to Cesium or CesiumUnminified in Build results in

import Cesium = require('cesium');
returning an empty object.

However, the Cesium file can be properly loaded from the sources provided in node_modules/cesium/Source. By removing format: 'cjs' from the cesium package and changing the mapping to 'cesium': 'npm:cesium/Source', I was able to execute this code:

 import Cesium = require('cesium');
 console.dir(Cesium.Viewer);

which resulted in:

 function Viewer(container, options)

being printed out in the console. The actual functionality of this is uncertain at this point.

Answer №3

I successfully integrated Cesium with Angular 2 and SystemJS after making some tweaks to the config file, as the solutions shared previously didn't quite work in my case.

Here is the updated systemjs.config.js file:

(function (global) {
  global.CESIUM_BASE_URL = './node_modules/cesium/Build/CesiumUnminified';
  System.config({
    paths: {
      // paths serve as alias
      'npm:': 'node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
     ...
     'cesium': 'npm:cesium/Build/CesiumUnminified'
     ...
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
  ...
  'cesium': {
    main: './Cesium.js',
    meta: {
      '*.js': {
        format: 'global'
      }
    }
  }
}
});
})(this);

Additionally, I added this line to app.component.js:

import 'cesium';

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Executing an http.get request in Angular2 without using RxJS

Is there a method to retrieve data in Angular 2 without using Observable and Response dependencies within the service? I believe it's unnecessary for just one straightforward request. ...

What is the best way to convert a date to ISO 8601 format using JavaScript? Are there any built-in functions or methods in

Currently, I am using this function to set the duration: const setDuration = () => { const currentDate = new Date(); const newDate = new Date(currentDate.getTime()); const year = newDate.getUTCFullYear(); const m ...

Resetting the Angular2 poller in an ng-bootstrap accordion

I am currently utilizing a multi-dimensional array connected to a reactive poller that waits for a database state update. Interestingly, when I initially load the state once, the user interface functions as intended. However, a challenge arises when I act ...

It appears that Jest is having trouble comprehending the concept of "import type"

We've just completed a major update to our monorepository, bringing it up to date with the following versions: Nx 14.3.6 Angular 14.0.3 Jest 28.1.1 TypeScript 4.7.4 Although the compilation process went smoothly after the upgrade, we encountered num ...

Is there a way to effectively refresh in Angular while using JBoss 6.4?

In my configuration of the standalone.xml file, I have set up the following rules inside subsystem tags: <rewrite name="rule-2" pattern="^((?!.*(rest)).*)\/([\w\-]+)\/([\w\-]+)$" substitution="/$1/index.html" flags="L"/> ...

Converting numerical values into currency format using Angular

Can anyone provide guidance on how to format a number received from the API as currency in Angular 15? This is what my HTML currently looks like: <thead class="fixed-top cabecalhoTabela"> <mat-card-header> & ...

Issues with the radio-inline class in Angular and Bootstrap causing functionality errors

Trying to align my radio buttons on one line using the radio-inline class from bootstrap. Here's my code: <label>Fattura a carico di </label> <label class="radio-inline control-label"><input type="radio" value="banca" n ...

Caution: Npm Angular alert during package installation

I keep encountering npm warnings while attempting to install packages: $ npm install npm WARN @angular/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ee8d81839e87828b9cc38d8287aedfdec0dec0dc">[email protected]</a> ...

Executing test units in Angular

While setting up unit tests for my Angular app, I expect the ngInit function to be called. Component.ts: ngOnInit() { this.topToolBarService.change.subscribe(customer => { this.filter.customerid = customer; this.customerid = customer; ...

An error occurred with code 1 when running the command "npm run build -- --prod"

I am currently working on a project in Visual Studio 2017 using Asp.Net Core 2 and Angular 5. While attempting to publish my project, I encountered the error message 'The command "npm run build -- --prod" exited with code 1' in the error list wi ...

Protractor Browser Instance Failure

We have encountered an issue with our UI suite failing in Chrome during the login process. Initially, we thought it might be due to upgrading to Chrome 79, as the problems arose simultaneously. Interestingly, the login functionality still works smoothly in ...

Navigating to the detail page following a POST request in RTK query: A step-by-step guide

In my React RTK-query form, I am facing an issue where after a POST request is made, the form should navigate to the next step. However, in order to do that, I need to obtain the id of the newly created record. The backend auto-increments the id and does n ...

Having trouble installing sub npm dependencies for a private npm module

I've created an npm private repository using Sinopia and published an app that is a complete end-to-end application built with Angular2 on the UI side. The package.json file contains dependencies such as @angular/core and animations. However, when I ...

How to correctly deserialize dates in Angular 5

When working with Angular 5, I have encountered an issue where JSON data from an API is not properly deserialized into dates within an array. My model includes a definition like this: export interface ProcessDefinition { _id?: string; proces ...

Creating Angular unit test modules

When it comes to creating unit test cases for an Angular app, the application functionality is typically divided into modules based on the requirements. In order to avoid the need for repeated imports in component files, the necessary components, modules, ...

Angular 2: Converting JSON data into an array

I am working with JSON data that contains vendor fields and I need to extract unique vendors into an array. Can someone provide guidance on how to achieve this in an Angular2 component? Here is the sample data: [{"category": "Living Room", "vendor": "Fle ...

Trouble with updating a variable within a loop in Cypress

During my experience with writing Cypress tests, I came across an issue that is preventing me from updating a specific variable. The goal of my test is to run a loop and update the questionId variable within each iteration for making API queries. However, ...

Encountering ReferenceError when attempting to declare a variable in TypeScript from an external file because it is not defined

Below is the typescript file in question: module someModule { declare var servicePort: string; export class someClass{ constructor(){ servicePort = servicePort || ""; //ERROR= 'ReferenceError: servicePort is not defined' } I also attempted t ...

Angular 2: Creating a Reusable Object for Uniform JSON Structures

I am facing an issue with JSON data as I have 3 tables in my database named "dictionary" with the same structure but different column names: {"id":1,"test_1":"test"},{"id":2,"test_1":"lalala"} - first JSON {"id":1,"test_2":"****"},{"id":2,"test_2":"afe ...

Angular 5: Validate and combine values from multiple input fields

I have a challenge in validating multiple number input fields by calculating their sum and creating a unique Validator for Angular. Each input field is formatted like this: <input type="number" min="0" max="10"> There are several number inputs, ea ...