Angular 2 - Error: Unable to access the property 'createMessage' as it is undefined

I want to import a JavaScript file into my Angular 2 project without having to rewrite it in Typescript. However, when everything is connected correctly, I encounter the following error...

"EXCEPTION: TypeError: Cannot read property 'createMessage' of undefined"

Here are the relevant files...

applicationAPI.js

var myApplication = myApplication || {};

(function(myApplication) {

myApplication.Message = function() {
    this.m_messageContents = "New Message";
};

myApplication.Message.prototype.getApplicationMessageContents = function() {
    return this.m_messageContents;
};

myApplication.SystemFactory = (function(){
    var factory =        
    {
        createMessage: function() {
            return new myApplication.Message();
        }
    };
    return factory;
}());

}(myApplication));

applicationAPI.d.ts

declare module "myApplicationAPI" {

export interface Message {
    getApplicationMessageContents(): string;
}

export class SystemFactory {
    static createMessage(): Message;
}

}

Interestingly, the code works with a slight change in applicationAPI.js while using the same applicationAPI.d.ts file.

applicationAPI.js

(function() {

this.Message = function() {
    this.m_messageContents = "New Message";
};

this.Message.prototype.getApplicationMessageContents = function() {
    return this.m_messageContents;
};

this.SystemFactory = (function(){
    var factory =        
    {
        createMessage: function() {
            return new this.Message();
        }
    };
    return factory;
}());}());

Any ideas on what else needs to be included for this specific scenario to work? It's not clear to me...

This is where the call originates from...

home.component.ts

import { Component, OnInit } from '@angular/core';
import * as myApp from "myApplicationAPI";
@Component({
moduleId: module.id,
selector: 'app-home',
templateUrl: 'home.component.html',
styleUrls: ['home.component.css']
})
export class HomeComponent implements OnInit {
title: string;

constructor() {}
ngOnInit() {
this.title = myApp.SystemFactory.createMessage().getApplicationMessageContents();
}
}

Answer №1

It seems like there is a problem with exporting from applicationAPI.js, making it impossible to import anything from it. When you use

import * as myApp from "myApplicationAPI";
, the expected outcome may not be what you think.

The initial reaction might be to export myApplication, but it is advisable to export classes and interfaces instead of instances. Let Angular's Dependency Injector handle the instances for better organization.

A recommended pattern could look something like this:

applicationAPI.ts

import Injectable from '@angular/core';
// You can either define Message here or import it
// If defined here, make sure to export it

@Injectable
export class Api {
  static createMessage(): Message {
    return new Message();
  }
}

home.component.ts

import Api from 'applicationAPI';
...
  constructor (private api: Api) {...}

If your bootstrap call currently looks like bootstrap(HomeComponent), consider updating it to

import Api from 'applicationAPI';
...
bootstrap(HomeComponent, [Api]);

This ensures that every injected instance of Api remains the same each time, unless the methods in the class are all static.

.d.ts files serve as references for the typescript compiler, indicating that there is something resembling the specified definition. These files do not execute or show up in the browser. If Message is solely defined in a .d.ts file, using new Message in javascript will not work because there won't be a clear definition for Message when the code runs in the browser.

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

In what ways can you toggle the visibility of table rows and data dynamically with the onchange event in HTML?

I'm dealing with an HTML code that can dynamically change table data based on user selection. Here's the snippet of my HTML code: Select an option: <select name='set' id="set" class="selectpicker" onchange='displayFields(this. ...

I am interested in redirecting command line output to a file rather than displaying it in the standard

Is it possible to use child-process and spawn in node.js to execute a command and save the output to a file instead of displaying it on the standard output? test.js const expect = require('chai').expect; const { spawn } = require('child_pr ...

Numerous points of interaction within ion-item

Within my ion-list, each ion-item contains a link to navigate to the next page. When tapping on an ion-item, it successfully navigates to the detail page. The problem arises when there is a button inside each ion-item that triggers an action. Tapping on t ...

Changing true/false values to Yes or No in Angular array output

I am working with an array that is structured as follows: { "Tasks": [ { "TaskID": 303691, "TaskName": "Test1", "TaskType": "Internal", "Status": "Processing", "IsApproved": false, "RowNumber": 1 }, { ...

Navigating in React: A Guide to Switching Components

I'm currently working on a landing page project using React. The goal is to have a consistent navigation bar across all sections of the website, with only the active state changing based on user interaction. Within my App.js file, I've implement ...

Angular: Having trouble accessing method within scope

I am attempting to utilize a method from my $scope controller, which is imported from a Factory, and execute it using the onclick method in an Ionic-based HTML. However, I am encountering the issue of getting undefined and I am unsure of the reason behind ...

What is the most efficient method for appending /.json to the conclusion of express routes?

I am currently transitioning a DJANGO API to Node.js and have been tasked with ensuring that routes support the .json extension at the end. For instance, sending a GET request to /users/:id/.json should return a JSON object representing the user. The cha ...

Type of event triggered by user file upload via INPUT element

I have a piece of code that reads the contents of a locally stored file. Here is what it looks like: onFile(event: any) { console.log(event); const file = event.target.files[0]; const reader = new FileReader(); reader.onloadend = (ev: any) => { ...

Changing the default yarn registry for a specific project

Typically, I fetch packages from the internal server by using the command: yarn config set registry http://custom-packages-server.com However, for a new project, I want to switch back to the default registry without affecting other projects. If I try cha ...

Activate the opening of a .docx file in a new tab by utilizing an anchor tag

I have attached a docx file containing the terms and conditions for our project. Now, I would like to open it in a new tab. By clicking this link, you can view the <a title="click to view terms and conditions" style="color:blue;" target="_blank" href ...

How can these lines be drawn in a simple manner?

I have been using the div tag to create a line, but I'm looking for an easier solution. If you have another method in mind, please share it with me. #line{ background-color:black; height:1px; width:50px; margin-top:50px; margin-left:50px; f ...

Tips for obtaining two altered Observable<[]> from a sole Observable<[]>

I am working with an Observable<Person[]> where the Person interface is defined as follows: export interface ToolfaceData { age: number; name: string; } My goal is to generate two separate Observable<Person[]>s, one in which we add 2 t ...

What is the best way to integrate JavaScript libraries into my NPM build process?

My current website is built using HTML and CSS (with SCSS) and I have been using an NPM build script. Now, I am looking to incorporate some JavaScript libraries into my site, such as lozad. I have already downloaded the necessary dependencies for the libr ...

What steps can be taken to retrieve data from a database table using JavaScript?

I am encountering a very peculiar issue. The values that I need are visible when I receive them as a message from the server-web console. However, when I try to retrieve them using a for loop, I encounter an error 05-22 18:58:23.203: I/Web Console(29392): ...

Validating data with Joi can result in multiple error messages being displayed for a single field

I'm attempting to implement a validation flow using the joi package, which can be found at https://www.npmjs.com/package/joi. 1) First, I want to check if the field category exists. If it doesn't, I should display the error message category requ ...

Passing PHP array to JavaScript in a specific format

After running the code provided, I find that the data returned is in an array format but unfortunately not easily referenced. AJAX: $.ajax({ url: './FILE.php', type: 'post', data: {'action': 'allfolders'}, ...

Turning Typescript into Javascript - the How-To Guide

Currently following Shopify's Node Api tutorial to implement a Redis store in my project. The tutorial provides code in typescript, but my entire project is in javascript (React/nextjs). I've been struggling to convert the code to javascript for ...

What are some ways to modify attributes in a jQuery datatable?

Upon loading the page, I initially set serverside to false. However, under certain conditions, I need to change serverside to true without altering any other attributes. For example: $(tableID).DataTable({ serverSide : false; }); Changing it to: $(t ...

By harnessing a JSON response

After sending an ajax request, the server's response is as follows: {"error":false,"success":true} The ajax code used: $.ajax({ url: '/update', type: 'post', data: $(this).serialize(), success: function(response) ...

How can I create a customized placeholder effect for the Paytm login page text box?

Looking to create a placeholder effect on the text boxes for a Paytm login page? https://i.sstatic.net/sox0a.png ...