What is the proper way to access the global `angular` variable in Angular and TypeScript when using AngularJS?

I'm currently integrating an Angular 4 component into a large monolithic AngularJS application. The challenge I face lies in the restrictions of the AngularJS project's build system, which limits me to only modifying the project's index.html. This means that my only option is to include additional <script> tags to load my Angular code. My main concern now is how to access the global angular variable within my Angular project's TypeScript files so I can downgrade the Angular component and make it compatible with AngularJS. It's crucial for me to achieve this without adding the entire AngularJS library as a dependency to my Angular project since it's already bundled within the AngularJS project's JS files that are loaded by the index.html.

To provide more context on the issue at hand: I have followed the steps outlined in the upgrade guide to bootstrap the AngularJS app from Angular. Here's a snippet from the app.module.ts file of the Angular project:

// src/app/app.module.ts of the Angular project
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { UpgradeModule } from '@angular/upgrade/static';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    UpgradeModule
  ]
})
export class AppModule {
  constructor(private upgrade: UpgradeModule) { }
  ngDoBootstrap() {
    // Bootstrap AngularJS app
    this.upgrade.bootstrap(document.documentElement, ['my-angularjs-app']);
  }
}

The configuration files src/main.ts and src/app/app.component.ts remain unchanged compared to a default $ ng new my-app project. Upon running $ ng build --prod to generate production-ready JavaScript files, I can then embed these files in the AngularJS project's index.html as described earlier. (It's worth noting that the Angular files are loaded after the AngularJS files.)

My goal now is to expose AppComponent to AngularJS. According to this section of the guide, I should add the following lines to the existing app.module.ts:

import { downgradeComponent } from '@angular/upgrade/static';

angular.module('my-angularjs-app')
  .directive(
    'my-ng2-component',
    downgradeComponent({ component: AppComponent }) as angular.IDirectiveFactory
  );

However, the TypeScript compiler throws errors due to the absence of the angular variable. I've attempted various solutions but none have been successful:

  1. Adding a line like declare var angular: any or let angular = window.angular resulted in a Cannot find namespace 'angular' error when including the downgrade code.
  2. Including @types/angular as a dependency and having a line such as
    import * as angular from 'angular'
    produced a
    Module not found: Error: Can't resolve 'angular'
    error when adding the downgrade code.
  3. Including a line
    /// <reference path="../../node_modules/@types/angular/index.d.ts" />
    at the top of the file also led to issues.
  4. Similarly, using
    /// <reference types="angular" />
    didn't resolve the problem either.

The errors resulting from options 3) and 4) were along the lines of:

'angular' refers to a UMD global, but the current file is a module. Consider adding an import instead.

These issues seem to be connected to discussions on GitHub regarding:

Is there a definitive solution to this problem? The upgrade guide lacks clarity on this specific matter.

Answer №1

After numerous attempts and experimentation, I eventually discovered a variation that appears to be effective. I included the following code snippet in app.module.ts:

import { downgradeComponent } from '@angular/upgrade/static';

declare var angular: any; // <-- Newly added declaration

angular.module('my-angularjs-app')
  .directive(
    'my-ng2-component',
    downgradeComponent({ component: AppComponent }) // <-- Notice no need for type conversion here anymore.
  );

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

Guide to setting the current slide in your ngx owl carousel using Angular

Looking for a solution to dynamically set an active slide based on index within a carousel. Attempted to apply the classes "active" and "center". The newsId variable in the example below is retrieved from another page and has been verified. <owl-carouse ...

Angular 4 animation for smooth sliding down

Attempting to add animation to my webpage has presented a challenge: I have a content div on my page, along with a button that triggers the opening of another div above the content. My goal is to have this top div fade and slide into view while simultan ...

Timer in AngularJS to periodically check the server for polls

Currently, I find myself in a situation where it is necessary to periodically request data from my server. After researching how others are tackling this issue in angularjs, I must admit that I am feeling quite bewildered. While some examples showcase sim ...

The concept of callback function overloading using generic types in TypeScript

Is there a way to define a callback type in TypeScript that can accept a variable number of generic type arguments while keeping the number of arguments fixed? For instance: export interface CustomFn { <T1>(value1: T1): boolean <T1,T2>(va ...

In my attempt to assess the correlation between value 1 and a value in the preceding object, I am utilizing the *ngFor directive

Attempting to compare 2 entries in an *ngFor loop. The code should compare the value at the current object to a value at the previous object. <ng-container *ngFor="let item of s_1.comments[0]; index as b"> <article class="message i ...

Displaying three tables in each row using ng-repeat, with the ability to repeat the process multiple times

Is it possible to repeat a table multiple times with each set of three tables in the same line using AngularJS and Bootstrap? I am unsure how this can be achieved with ng-repeat. table 1 | table 2 | table 3 table 4 | table 5 | ... <div ng-repeat="zo ...

Resolving the scope of $modal with ng-bind-html in AngularJS Ui-Bootstrap

Seeking help with passing HTML form controls as parameters to an AngularJS modal. While successful with hard-coded controls, encountering challenges with soft-coded ones. Attempted to locate an isolated scope solution and stumbled upon mentions of transclu ...

Having some trouble while attempting to set up the next-auth@beta package due to an error

Currently encountering the following error message: code EUNSUPPORTEDPROTOCOL Unsupported URL Type "workspace:": workspace:* I have made sure to update my node to the most recent recommended version. In a previous project, I successfully instal ...

What are the drawbacks of starting with Angular CLI?

Contemplating whether to incorporate Angular CLI into my upcoming project has been on my mind. My main motivation for considering it is to bypass the complexities of setting up a new project and instead focus on mastering the new version of Angular while c ...

TypeScript and Express create a powerful array combination capability within the type system

After defining the EventType as either "TYPE A" or "TYPE B", I am looking to create a type for an array that can only contain one or both of these event types. Simply typing it as an EventType[] allows duplicates, which is not ideal. type Test = EventType ...

Dynamically incorporate controls in Angular4.4-RxJs post API data retrieval

I am currently working on creating a form that dynamically adds checkboxes based on data received from an API. After successfully receiving the data in JSON format, it looks like this: [ { "code": "TicketTypeRead", "name": "Read Ticket Types" }, { ...

Monitor the user's attendance by utilizing two separate for loops

I'm currently developing an angularjs attendance tracking system and I'm facing challenges when it comes to accurately counting the number of days an employee is absent. Despite attempting to solve this issue with two nested for loops, I am still ...

Utilizing Express for Angular serverside rendering: Best practices explained

I attempted to utilize Angular's Server Side Rendering and encountered difficulties with a very basic scenario. Challenges Challenge 1 Expected outcome : Using express to simplify the angular app by only returning a "welcome object" Actual outcome : ...

Trouble with references in Vue TypeScript when trying to access child component methods

I'm encountering an issue with calling a function in a child component while using typescript <notification ref="notification"></notification> <button @click="$refs.notification.show()"></button> Is there a ...

Angular's modalservice fails to recognize the enter key input

I am currently implementing a Modal dialog using ui.bootstrap & angular modal service <div id="modalDialog" class="modal-dialog"> <div class="modal-header"> <h2 style="text-align: center">{{modalOptions.headerText}}</h2> ...

Steps to display a modal within an inactive tab:

I have been using ngx-bootstrap tabset, although I believe this issue could apply to all bootstrap tabs as well. <tabset> <tab class='active'> <angular-modal-component> </angular-modal-component> </tab> <tab> & ...

Issues Arise with Nativescript Layout When Content is Not in View on iOS

This problem has been giving me a hard time for the past few days. I hope someone can help me figure out what's wrong. I have a view that shows a nested list inside a main list. The main list contains header details. Everything looks fine when the in ...

What is the process of hosting an Angular application on a pre-existing Node.js server?

I am currently working on an Angular 6 application that communicates with an existing Node.js API application. Up to this point, I have been using the following command to run and build my Angular application: ng serve Now, I am interested in serving m ...

Tips for broadcasting a router event

Currently, I am working with 2 modules - one being the sidenav module where I can select menus and the other is the content module which contains a router-outlet. I am looking for the best way to display components in the content module based on menu selec ...

Angular is unable to modify the value of 'name' since it is either a constant or a property that cannot be modified

I am encountering an error that says "Cannot assign to 'name' because it is a constant or a read-only property" when trying to send data to the API. Does anyone know how I can solve this issue? Thank you. onSubmit() { const name = this.backU ...