Method with undefined constructor parameter in Typescript

Understanding how to effectively use Typescript and Angularjs in conjunction has been a challenge for me. Despite reading numerous blog posts and consulting the official documentation for both projects, the concepts just haven't fully clicked.

My Angular controller requires two dependencies: $scope and a custom service named greetingService. I have set up a main app Angular module where I have connected the controller and service. By including log statements in my Typescript constructors, I can verify that the dependencies are being injected correctly. However, when attempting to utilize a dependency within the controller, it appears as undefined. The code snippet below showcases this issue more clearly:

declare var angular;

module App.Services {
    export class GreetingService {

        constructor(private $http) {
            console.log("In greeting service constructor");
            console.log($http);
        }

        getGreetingsPromise() {
            return this.$http.get('/greetings.json');
        }
    }
}

module App.Controllers {
    export class GreetingController {

        static $inject = ['$scope', 'greetingService'];
        constructor(public $scope, public greetingService: App.Services.GreetingService) {
            this.$scope.greeting = "This will be a greeting.";
            this.$scope.greet = this.greet;

            console.log(greetingService); // this is defined and looks right
        }

        greet(language: string) {
            console.log("Greeting...");
            console.log(this.$scope); // this is undefined
            console.log(this.greetingService); // this is undefined
            var greetingPromise = this.greetingService.getGreetingsPromise();
            greetingPromise.then(data => this.$scope.greeting = data[language]);
        }
    }
}


var mainApp = angular.module('mainApp', []);
mainApp.controller('greetingController', ['$scope', 'greetingService', App.Controllers.GreetingController]);
mainApp.service('greetingService', App.Services.GreetingService);

Below is the Angular template (which displays "This will be a greeting" as intended from the constructor initialization):

<div class="jumbotron">
    <div ng-controller="greetingController">
        <p class="lead">{{greeting}}</p>
        <button ng-click="greet('english')">Greet me</button>
    </div>
</div>

Answer №1

Here is a crucial line to pay attention to:

this.$scope.greet = this.greet

This specific line is causing the issue. By simply copying the function reference to a scope property, you are risking the scenario where it is called with scope this not being the controller instance. It gets determined by the caller (in this case, this should actually be the scope itself inside the greet function when called from the template) apart from the bound functions. A quick fix would involve using function.bind. For example:

this.$scope.greet = this.greet.bind(this)
, in which you generate a bound function – a function reference tied to the controller instance. Alternatively, you can utilize an arrow function and assign it as a reference, resulting in TypeScript converting any this instances to a cached variable like _this:

   greet = (language: string) => {
        console.log("Greeting...");
        console.log(this.$scope); // this will be undefined
        console.log(this.greetingService); // this will be undefined
        var greetingPromise = this.greetingService.getGreetingsPromise();
        greetingPromise.then(data => this.$scope.greeting = data[language]);
    }

If possible, consider using the controller As syntax (provided your Angular version supports it, or upgrade if not) instead of directly interfacing with the scope to avoid having to perform all these modifications.

For instance:

export class GreetingController {
    greeting :string;

    static $inject = ['greetingService'];

    constructor(public greetingService: App.Services.GreetingService) {
        this.greeting = "A greeting message.";
    }

    greet(language: string) {
        var greetingPromise = this.greetingService.getGreetingsPromise();
        greetingPromise.then(data => this.greeting = data[language]);
    }
}

and

<div class="jumbotron">
    <div ng-controller="greetingController as vm">
        <p class="lead">{{vm.greeting}}</p>
        <button ng-click="vm.greet('english')">Say Hello</button>
    </div>
</div>

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

Issue with Socket.io Client: Consistently receiving error messages for an incorrect

Here is the server-side code: import http from 'http'; import Koa from 'koa'; import { Server } from 'socket.io'; (async () => { const app = new Koa(); var server = http.createServer(app.callback()); var io = new Se ...

The function mustAsync onSuccess is not present in this type (typescript)

I currently have 2 mutations that are functioning well. However, I encountered an issue when attempting to implement onSuccess and invalidateQueries. The error message displayed is as follows: Property 'mutateAsync' does not exist on type '{ ...

Ways to retrieve a variable from outside of a function

I am in need of sending the following batch data to the database, but I am facing difficulties in including the course_id along with the batchData. Currently, I am retrieving the course_id from another service that fetches data from a course table. I am ...

Front end authentication failed (Angular/Spring stack)

Link to my front end code: http://embed.plnkr.co/toe4XO/. I made adjustments to the authentication/service.js file, see below: 'use strict'; angular.module('Authentication') .factory('AuthenticationService', ['Base ...

Angular 7 TypeScript code not updating value

UPDATE: I'm having trouble with my code not updating the selected value with the new one entered in the input field "newVb". The error message says 'this.newVarde' is undefined when it reaches the line 'this.selectedVarde = this.newVard ...

How to add icons to HTML select options using Angular

Looking for a way to enhance my component that displays a list of accounts with not only the account number, but also the currency represented by an icon or image of a country flag. Here is my current component setup: <select name="drpAccounts" class= ...

Component does not support camelCase names

My current challenge involves creating a navbar component where I need to share some data from the main page to the component. After spending several hours researching how to use components, I have been unable to find an explanation as to why camelCase var ...

Unexpected package version changes occurring due to bower install

I am currently using bower 1.3.12 Here is the content of my bower.json file: { "name": "my_project", "version": "0.0.0", "authors": [ "ME <<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="660b0326030b070f0a4805090b ...

Issues arise when initiating the Node.js server with Gulp and encountering a breakdown in live reload functionality, specifically while working with an Angular application that utilizes html5 mode

I have been facing a persistent issue that needs solving. The Scenario: The problem arises when I start my local server with Live Reload using Gulp. My Angular app starts up without any issues, but whenever I make a file change, Live Reload breaks my ap ...

Unable to display text overlay on image in AngularJS

I am experiencing an issue with displaying captions on image modals. .controller('HomeController',['dataProvider','$scope','$location', '$modal', '$log', 'authService', function ...

Guide to implementing bidirectional data binding for a particular element within a dynamic array with an automatically determined index

Imagine having a JavaScript dynamic array retrieved from a database: customers = [{'id':1, 'name':'John'},{'id':2, 'name':'Tim}, ...] Accompanied by input fields: <input type='text' na ...

Develop a TypeScript class that includes only a single calculated attribute

Is it advisable to create a class solely for one computed property as a key in order to manage the JSON response? I am faced with an issue where I need to create a blog post. There are 3 variations to choose from: A) Blog Post EN B) Blog Post GER C) Bl ...

Exploring NestJS: Leveraging the @Body() Decorator to Retrieve Request Body Data

import { Controller, Post, Body } from '@nestjs/common'; import { MyService } from 'my.service'; import { MyDto } from './dto/my.dto'; @Controller('my-route') export class MyController { constructor(private rea ...

Using Vue.js 2 on multiple HTML pages with Typescript and ASP.Net Core

My ASP.Net Core MVC project utilizes VueJs2 for more complex tasks, with each view having its own corresponding js file. The directory structure is as follows: ├ Controllers\HomeController.cs (with actions Index & Details) ├ Scripts\Hom ...

Recursively map elements of a TypeScript array to keys of an object

I am looking to create a structured way to specify paths for accessing objects, ensuring that the path is correctly typed based on the object type. Let me illustrate with an example. Consider the following data: const obj = { name: 'Test', ...

Need help in NestJS with returning a buffer to a streamable file? I encountered an error stating that a string is not assignable to a buffer parameter. Can anyone provide guidance on resolving this issue?

The issue description: I am having trouble returning a StreamableFile from a buffer. I have attempted to use buffer.from, but it does not seem to work, resulting in the error message below. Concern in French language: Aucune surcharge ne correspond à cet ...

``Error encountered when attempting to navigate AngularJS route with trailing forward slash

I have a link that is working perfectly fine, like this: when('/videos', { templateUrl: 'partials/partial1', controller: 'MyCtrl1' }). But when I add a named group to the route like this: when('/videos/:video_id&ap ...

Enhancing event listener using AngularJS and Jasmine: spying on callback functions

Can someone assist me with spyOnning a method connected to an event using scope.$on in a factory service, using Jasmine? The actual method is being called instead of the spy. Here is a plinkr I created showcasing the issue: http://plnkr.co/edit/2RPwrw?p=pr ...

When trying to use global.mongoose in Typescript, a type error is being thrown

I'm attempting to incorporate caching into my database connection file in order to streamline the process for my next.js application and avoid repeating the connection step every time I interact with the database. import mongoose from 'mongoose&a ...

Using HelloJS and AngularJS for an asynchronous call to the login function with oAuth

I've been working on integrating HelloJS into my AngularJS app. According to the documentation, in order to authenticate I need to call the login function like this: hello("google").login().then(function(){ }); After that, I should listen for the &a ...