TypeScript + Class + createjs.EventDispatcher - createjs

I'm trying to use the createjs EventDispatcher as a way to dispatchEvents from a class. I'm extending my class using createjs.EventDispatcher and using the dispatchEvent to trigger the event.
I get the following error when this line isthis.dispatchEvent(createJSEvent); executed:
Uncaught InvalidStateError: Failed to execute 'dispatchEvent' on 'EventTarget': The event provided is null.
Simplified TypeScript code to demonstrate what I'd like to do:
export class deviceOrientation extends createjs.EventDispatcher {
constructor() {
super();
// wait 2 seconds and then fire testDispatch
setTimeout(this.testDispatch(), 2000);
}
testDispatch():void {
var createJSEvent:createjs.Event = new createjs.Event("change", true, true);
this.dispatchEvent(createJSEvent);
}
}
// This is the starting function
export function appExternalModuleTest(): void {
let _deviceOrientation: deviceOrientation;
_deviceOrientation = new deviceOrientation();
_deviceOrientation.addEventListener("change", () => this.changeOrientation());
//_deviceOrientation.on("progress", () => this.changeOrientation());
}
export function changeOrientationi(event: Event): void {
console.log('orienationHasChanged ');
}
I'm using easeljs-0.8.1.min.js
I'm not sure if this is possible with CreateJS. Is there a better approach?
Any help is greatly appreciated.

The problem looks strange, because I do almost the same in my project and don't have any problems.
In a nutshell, I have a d.ts file for createjs classes declaration and I use these declarations in my "normal" typescript classes.
For example:
d.ts:
declare module createjs
{
export class EventDispatcher
{
addEventListener(type: string, listener: any, useCapture?: boolean): void;
removeEventListener(type: string, listener: any, useCapture?: boolean): void;
removeAllEventListener(type?: string): void;
dispatchEvent(event: Event): boolean;
}
export class Event
{
public type: string;
public target: any;
public currentTarget: any;
constructor(type: string, bubbling?: boolean, cancelable?: boolean);
clone(): Event;
}
}
Normal class:
module flashist
{
export class TestEventDispatcher extends createjs.EventDispatcher
{
public constructor()
{
super();
}
public testDispatch(): void
{
var tempEvent: createjs.Event = new createjs.Event("test");
this.dispatchEvent(tempEvent);
}
}
}
And somewhere else in the code you should create an instance of the TestEventDispatcher class. Something like:
this.testDispatcher = new TestEventDispatcher();
this.testDispatcher.addEventListener("test", (event: createjs.Event) => alert("Test Event Listener"));
this.testDispatcher.testDispatch();
I've just tested the code and it works for me.
The only idea I have is to make sure that the easel.js file is loaded before your main app files.

Related

"Cannot read property 'Component' of undefined" while calling a method of one component from another via params.context in Angular 8

export class ChildMessageRenderer implements ICellRendererAngularComp {
public params: any;
#ViewChild(SecComponent, { static: false }) accComponent: SecComponent;
agInit(params: any): void {
this.params = params;
}
public loadRequestsHistory() {
this.params.context.AccountBatchAuditComponent.loadRequestsHistory('36');
}
}
I am trying to call method of SecComponent from ChildMessageRenderer. #ViewChild is throughing error in the console. Can someone help on this issue?

ViewManager receiveCommand is deprecated?

I've recently noticed in the react-native source code that the following method:
public void receiveCommand(#NonNull T root, int commandId, #Nullable ReadableArray args)
of the ViewManager class is marked as deprecated. Therefore, I tried to replace it with an overloaded version that is not marked as deprecated:
public void receiveCommand(#NonNull T root, String commandId, #Nullable ReadableArray args)
but this one never gets invoked. I imagine I also might need to change some other methods, but I cannot find any information what else has to be done, there is no migration guide that I could follow.
Does anyone know how to properly use the new, non-deprecated receiveCommand method?
The source code of the ViewManager can be found here:
https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java
The new, non-deprecated version of receiveCommand will get called if a String is sent as the second argument of the dispatchViewManagerCommand from your React Native code. There is no need to override getCommandsMap() anymore.
Example:
CustomViewManager.kt (In Kotlin, should be easy to convert to Java)
class CustomViewManager : SimpleViewManager<CustomView>() {
...
override fun createViewInstance( context: ThemedReactContext): CustomView {
// code to instantiate your view
}
...
override fun getName(): String {
return "CustomView"
}
...
override fun receiveCommand(view: CustomView, commandId: String, args: ReadableArray?) {
when (commandId) {
"doSomething" -> doSomething()
}
}
MyComponent.js
import { View, requireNativeComponent, UIManager, findNodeHandle } from 'react-native';
...
const CustomView = requireNativeComponent('CustomView');
...
export default class MyComponent extends Component {
...
onDoSomething = async () => {
UIManager.dispatchViewManagerCommand(
findNodeHandle(this.customView),
'doSomething',
undefined,
);
};
...
render() {
return (
<View>
<CustomView
ref={(component) => {
this.customView = component;
}}
/>
</View>
);
}
}

Specialized Singleton implementation

I am looking for specialized singleton implementation, probably I might be using wrong terminology and hence looking for expert suggestion. Here is my scenario:
There is common code which can be called by ComponentA or ComponentB. I need to push telemetry data from the common code. Telemetry needs to have information that whether this common code get called by ComponentA or ComponentB.
So common code will have just this line of code:
telemetry.pushData(this._area, data);
where this._area tells the telemetry data is getting pushed for which component
I need to push telemetry data from multiple places so it would be good if object got created once and used through out the code lifetime
One option I can think of passing component context to the common code which in mind doesn't look right, hence looking for suggestion what kind of pattern one should use in this case?
This is what I am thinking
// Telemetry.ts file present in shared code
export class Telemetry extends Singleton {
public constructor() {
super();
}
public static instance(): Telemetry {
return super.instance<Telemetry>(Telemetry);
}
public publishEvent(data): void {
if (!this.area) {
throw new Error("Error: Initialize telemetry class with right area");
}
pushtelemetryData(this.area, data);
}
public area: string;
}
// Create Telemetry object from component A
Telemetry.instance().area = "ComponentA";
// Shared code will call telemetry publishEvent
Telemetry.instance().publishEvent(data);
Thanks
It's not a good pattern to use in TypeScript where you would generally inject dependencies.
If you must absolutely do it then you can do it by faking it somewhat:
namespace Telemetry {
var instance : SingletonSomething;
export function push(data: Any) : void {
if (instance == null) {
instance = new SingletonSomething();
}
instance.push(data);
}
class SingletonSomething() { ... }
}
and then you could call
Telemetry.push(data);
You can imitate the singleton pattern in typescript easily:
class Telemetry {
private static instance: Telemetry;
public static getInstance(): Telemetry {
if (Telemetry.instance == null) {
Telemetry.instance = new Telemetry();
}
return Telemetry.instance;
}
...
}
If you have your code in some sort of closure (module, namespace, etc) then you can replace the static member with:
let telemetryInstance: Telemetry;
export class Telemetry {
public static getInstance(): Telemetry {
if (telemetryInstance == null) {
telemetryInstance = new Telemetry();
}
return telemetryInstance;
}
...
}
But then you can also replace the static method with:
let telemetryInstance: Telemetry;
export function getTelemetryInstance(): Telemetry {
if (telemetryInstance == null) {
telemetryInstance = new Telemetry();
}
return telemetryInstance;
}
export class Telemetry {
...
}
At this point, in case you are using some sort of closure, you might ask yourself if you really need the class at all?
If you use this as a module:
// telemetry.ts
export interface TelemetryData {
...
}
export function pushData(data: TelemetryData): void {
...
}
Then you get exactly what you're looking for, and this is more of the "javascript way" of doing it.
Edit
In the telemetry module there's no need to know the users of it.
If the Telemetry.pushData function needs to have information about the object that called it then define an interface for it:
// telemetry.ts
export interface TelemetryData {
...
}
export interface TelemetryComponent {
name: string;
...
}
export function pushData(data: TelemetryData, component: TelemetryComponent): void {
...
}
Then in the other modules, where you use it:
// someModule.ts
import * as Telemetry from "./telemetry";
class MyComponent implement Telemetry.TelemetryComponent {
// can also be a simple string property
public get name() {
return "MyComponent";
}
fn() {
...
Telemetry.pushData({ ... }, this);
}
}
2nd Edit
Because you are using a module system, your module files are enough to make singletons, there's no need for a class to achieve that.
You can do this:
// telemetry.ts
let area: string;
export interface TelemetryData {
...
}
export function setArea(usedArea: string) {
area = usedArea;
}
export function pushData(data: TelemetryData): void {
...
}
Then:
Telemetry.setArea("ComponentA");
...
Telemetry.publishEvent(data);
The telemetry module will be created only once per page, so you can treat the entire module as a singleton.
Export only the functions that are needed.

How to handle exception twice

I have extended the ExceptionHandler class:
import {Injectable, ExceptionHandler} from '#angular/core';
export class FirstError extends Error {
handle() {
console.log("This is firstError handler");
}
}
export class AnotherError extends Error {
handle() {
console.log("This is AnotherError handler");
}
}
export class _ArrayLogger {
res = [];
log(s: any): void { this.res.push(s); }
logError(s: any): void { this.res.push(s); }
logGroup(s: any): void { this.res.push(s); }
logGroupEnd() {};
}
#Injectable()
export class CustomExceptionHandler extends ExceptionHandler {
constructor() {
super (new _ArrayLogger(), true);
}
call(exception: any, stackTrace = null, reason = null) {
// I want to have original handler log exceptions to console
super.call(exception, stackTrace, reason);
// If exception is my type I want to do some additional actions
if (exception.originalException instanceof Error) {
exception.originalException.handle();
}
}
}
My goal is to have super.call log the error to the console as original Angular2 ExceptionHandler, and additionally do my own exception handle. Unfortunately, in such a scenario super gets called only the first time the error is thrown. When the second, third .. occurs, the super is not get called. How to make it work so the original console.log logs the error to console, and additionaly error processing is also done?
I had the same problem but was able to get it working by passing false in the constructor for the second parameter (rethrowException).
constructor() {
super (new _ArrayLogger(), false);
}
The name of the parameter would suggest that the correct value is indeed true; seems a bit backward to me but it works.

Is there any way to use static typing with declared TypeScript modules?

I have this little TypeScript app for node.js that needs to connect to a MongoDB:
module Engine
{
export class EngineCore
{
public launch()
{
var mongo = require('mongodb');
var client = mongo.MongoClient;
client.connect('mongodb://localhost:27017/', (error, db) => {this.onDBConnect(db)});
}
private onDBConnect(db)
{
}
}
}
Now, I know that I'm getting a Db class on connect callback, but I can't figure out the way to explicitly type the db argument to the Db class. I'm using a DefinitelyTyped definition file for mongodb, it goes like this:
declare module "mongodb" {
export class MongoClient {
constructor(serverConfig: any, options: any);
static connect(uri: string, options: any, callback: (err: Error, db: Db) => void): void;
static connect(uri: string, callback: (err: Error, db: Db) => void): void;
}
export class Db {
constructor (databaseName: string, serverConfig: Server, dbOptions?: DbCreateOptions);
[...]
}
}
I've tried importing it like this:
module Engine
{
import MongoDB = require('mongodb');
[...]
}
But I'm getting the following error:
error TS2136: Import declarations in an internal module cannot reference an external module.
Is there any way to use the Db class for explicit typing from outside the module?
Have you tried re-positioning the import like this? the below compiles and runs for me
import mongo = require('mongodb');
module Engine
{
export class EngineCore
{
public launch()
{
var client = mongo.MongoClient;
client.connect('mongodb://localhost:27017/', (error, db) => {
this.onDBConnect(db);
});
}
private onDBConnect(db:mongo.Db)
{
console.log("connected");
}
}
}
var x = new Engine.EngineCore();
x.launch();