I tried to instantiate a javascript object in a typescript file, basically in an Angular Application but there is an error as object is not defined.
My JavaScript file:
import { EventEmitter } from 'events';
export default class Cursor extends EventEmitter {
constructor(el) {}
//some methods
}
My typescript file
First alternative :
declare var Cursor:any;
export class HomeComponent implements OnInit {
ngOnInit(): void {
const cursor = new Cursor();
console.log(cursor.emit('enter'))
}
}
=> ERROR ReferenceError: Cursor is not defined
Second alternative (importing js file)
import Cursor from '../utils/js/cursor';
export class HomeComponent implements OnInit {
ngOnInit(): void {
const cursor = new Cursor();
console.log(cursor.emit('enter'))
}
}
=> Property 'emit' does not exist on type 'Cursor'.
In that case there is an inheritance problem with class Cursor extending EventEmitter
Can someone give me an hand with that problem ?
Thanks
Related
I'm trying to call a JS function inside a component in my TS file, but I'm getting an exception.
Component
import '../../../assets/js/gantt/ganttMaster.js';
export class TaskComponent implements OnInit {
constructor() {}
ngOnInit() {
var r = new GanttMaster();
}
}
Error:
Error referecences error: GanttMaster is not defined
You need to change the way you import the .js file:
import * as gantt from '../../../assets/js/gantt/ganttMaster.js';
export class TaskComponent implements OnInit {
constructor() {}
ngOnInit() {
var r = new gantt.GanttMaster();
}
}
If you want to use GanttMaster among several components, you can import the .js file in angular.json and declare a constant in app.module.ts like declare const GanttMaster: any. Then you can use it in your application.
Hope this helps.
UPDATE
Alternatively, you can import it the way you've already done, but declare the function manually before the import:
declare const GanttMaster: any;
import from '../../../assets/js/gantt/ganttMaster.js';
export class TaskComponent implements OnInit {
constructor() {}
ngOnInit() {
var r = new GanttMaster();
}
}
Ref: https://stackoverflow.com/a/37084553/1331040
In my project i load a js file from assets, something like this:
add this JavaScript file in scripts array in angular.json file like as above you have added jquery library.
"scripts": [
.....
"src/assets/js/custom.js"
]
custom.js:
function myTest() {
alert('Welcome to custom js');
}
You need declare in your component
declare const myTest: any;
I'm trying to create a generic repository for every entity in the application
mongo-repository.ts
import { Document, Model, Types } from 'mongoose';
type MongooseModel<T> = Model<T & Document>;
export abstract class MongoRepository<T extends MongooseModel<T>> {
protected constructor(
protected readonly model: T,
) {}
}
user.repository.ts
import { User } from '../../../models/User';
import { MongoRepository } from '../../common/mongo/mongo-repository';
class Repository extends MongoRepository<User> {
constructor() {
super(User);
}
}
export const UserRepository = new Repository();
Actual results:
src/modules/user/repository/user.repository.ts:4:42 - error TS2304: Cannot find name 'User'.
4 class Repository extends MongoRepository<User> {
~~~~
Expected result:
Work.
However, I'm not getting this error message in super(User) but only in the generic declaration
Fixed,
Fix:
MongoRepository<T extends typeof Model>
class Repository extends MongoRepository<typeof User>
I want to isolate http interactions by creating data access objects from a class so that in a component I might simply get data like this:
// dashboard.component
import { AppUser } from './appuser.service'
export class DashboardComponent implements OnInit {
user: AppUser = new AppUser();
constructor() { }
ngOnInit() {
let id = JSON.parse(window.localStorage.getItem('session')).userId;
this.user.find(id) // 'find' is from base class
.subscribe(
// handle user data
);
}
}
I have defined a base class and a sub class like this:
// base-resource.service
import { HttpClient } from '#angular/common/http';
...
export class BaseResource {
private fullpath: string;
protected http: HttpClient;
constructor (path: string) {
this.fullpath = path;
}
find (id): Observable<Object> {
return this.http.get(this.fullpath + '/' + id); // this line throws Error!
}
}
// app-user.service
...
export class AppUser extends BaseResource {
constructor(data?) {
super('api/appusers');
}
}
However this generates an error: ERROR TypeError: Cannot read property 'get' of undefined from within the base class function.
My 'AppUser' instance is clearly inheriting find from 'BaseResource', but find is picking up the 'AppUser' instance as the value of this and http is not available. I have tried declaring http as public and private as well as protected, but that had no effect. I imagine I'm missing some bigger picture of how to extend classes.
As specifically as possible, i think my question is in how to abstract functions to a base class when they need access to the base class's context.
(using Angular 6.0.4)
EDIT
I updated the title as it became clear that this is a problem of instantiating the HttpClient service in a class.
The error is because nothing is instantiating HttpClient, so it is undefined when you come to use it.
You should inject HttpClient into AppUser, and pass it into BaseResource via the constructor
export class AppUser extends BaseResource {
constructor(HttpClient http) {
super(http, 'api/appusers');
}
}
And in base-resource.service
import { HttpClient } from '#angular/common/http';
...
export class BaseResource {
private fullpath: string;
protected http: HttpClient;
constructor (httpClient: HttpClient, path: string) {
this.fullpath = path;
this.http = httpClient;
}
find (id): Observable<Object> {
return this.http.get(this.fullpath + '/' + id); // this line throws Error!
}
}
I have a problem introducing TypeScript to our JavaScript project.
First I want to use TypeScript only in my part of the code, leaving the JavaScript untouched.
Now I try to use a JavaScript class in my TypeScript code, but I don't find a solution in the last days.
The head of my TypeScript class with import of the JavaScript:
import { BaseLogic } from "../baseLogic";
export class ClaimLogic extends BaseLogic {
...
The JavaScript class ("baseLogic.js"):
module.exports = class BaseLogic {
constructor(meta, logger) {
...
My *.d.ts file ("baseLogic.d.ts"):
export class BaseLogic {
meta: any;
log: any;
constructor(meta: any, logger: any)
}
The head of the compiled JavaScript:
const baseLogic_1 = require("../baseLogic");
class ClaimLogic extends baseLogic_1.BaseLogic {
...
As you see in the compiled JavaScript baseLogic_1.BaseLogic is used.
This results in following error:
TypeError: Class extends value undefined is not a constructor or null
With only baseLogic_1 after the extends keyword in the JavaScript file all is fine.
I have no idea about a solution and hope you can help me!
Your import suppose to be import * as BaseLogic from "../baseLogic";.
In that way you will get the Class that you put on module.exports.
The codesnipet in baseLogic.js exports the class.
module.exports = class BaseLogic {
constructor(meta, logger) {
...
}
You try to access with class ClaimLogic extends baseLogic_1.BaseLogic an object that includes the class BaseLogic
Solution
import BaseLogic from '../baseLogic'
// or: const BaseLogic = require("../baseLogic");
class ClaimLogic extends BaseLogic {
...
}
Is there a correct way to invoke a JavaScript function from a component in Angular 2 (TypeScript) ?
Here is my component :
import { ElementRef, AfterViewInit } from '#angular/core';
export class AppComponent implements AfterViewInit {
constructor(private _elementRef: ElementRef) {
}
ngAfterViewInit() {
/**
* Works but i have this error :
* src/app.component.ts(68,9): error TS2304: Cannot find name 'MYTHEME'.
* src/app.component.ts(69,9): error TS2304: Cannot find name 'MYTHEME'.
*/
MYTHEME.documentOnLoad.init();
MYTHEME.documentOnReady.init();
/**
* Works without error, but doesn't seem like a right way to do it
*/
var s = document.createElement("script");
s.text = "MYTHEME.documentOnLoad.init(); MYTHEME.documentOnReady.init();";
this._elementRef.nativeElement.appendChild(s);
}
}
Calling the JavaScript function directly result in an compilation error, but the syntax in the "compiled" JavaScript file (app.component.js) is correct :
AppComponent.prototype.ngAfterViewInit = function () {
MYTHEME.documentOnLoad.init();
MYTHEME.documentOnReady.init();
};
The 2nd way (appendChild) works without error, but i don't think (altering the DOM from typescript/angular) is the correct way to do it.
I found this : Using a Javascript Function from Typescript I tried declaring the interface :
interface MYTHEME {
documentOnLoad: Function;
documentOnReady: Function;
}
But the TypeScript doesn't seem to recognize it (no error in the interface declaration).
Thanks
Edit :
Following the answer by Juan Mendes this is what i ended with :
import { AfterViewInit } from '#angular/core';
interface MYTHEME {
documentOnLoad: INIT;
documentOnReady: INIT;
}
interface INIT {
init: Function;
}
declare var MYTHEME: MYTHEME;
export class AppComponent implements AfterViewInit {
constructor() {
}
ngAfterViewInit() {
MYTHEME.documentOnLoad.init();
MYTHEME.documentOnReady.init();
}
}
You have to tell TypeScript about external (JavaScript) declarations using declare. See https://www.typescriptlang.org/docs/handbook/writing-declaration-files.html
interface MyTheme {
documentOnLoad: Function;
documentOnReady: Function;
}
declare var MYTHEME: MyTheme;
Or anonymously
declare var MYTHEME: {documentOnLoad: Function, documentOnReady: Function};