Teckniel Posted May 5, 2021 Share Posted May 5, 2021 (edited) Hello, I got allot further in my goal to make a ribbon like menubar. But for some reason i had a error saying Sprite.On do not exist, so i had to edit the tsconfig file and add the line: "allowSyntheticDefaultImports": true, to the compiler options so after adding that i was able to use that methode. But here comes the problem: When i hit the Sprite Button -> it go's to the required function and print's in the console the message i provided, But when i want to acces the container from the UIMananger within the onButtonClick -> this.uiContainer i get error saying it's undifiend Anyone have a clue how to fix this? UI Manager Snippit (See: onButtonClick ) export class UiManager { private demoScene: Boolean = false; private uiContainer: Container = new Container; constructor(demo:Boolean) { this.demoScene = demo; this.uiContainer = this.GenerateMenuBar(); } public getUI(): Container{ return this.uiContainer; //Return the ui Correctly } private onButtonClick() :void { console.log("clickt on button"); let btnTest = this.createMenuButton(); // <<-- Error: this.createMenuButton is not a function console.log(this.uiContainer); // <<-- Error: Undefined this.uiContainer //Launch a event to show a sprite... } private GenerateMenuBar(): Container{ this.uiContainer.addChild( this.createMenuBackground(), this.createMenuButton(), this.createWallsnWindow(), ); return this.uiContainer; } private createMenuButton():Sprite{ console.log("Create MenuButton") var tmpSrite = Sprite.from('./src/Engine/assets/ui/btn_NewScematic.png'); tmpSrite.interactive = true; tmpSrite.buttonMode = true; tmpSrite.name = "menuButton"; tmpSrite.position.x = 10; tmpSrite.y = 59; tmpSrite.hitArea = new Polygon([40,0, 100,0, 100,40,40,40]); //Setup Hitbox tmpSrite.on('pointertap', this.onButtonClick); //Interaction... return tmpSrite; } Engine File -> Everything in here renders ok and uses the UIManager export class Engine { public renderer: Renderer; public loader: Loader; public world: Container; public graphics: Graphics; public fpsMax: number; public canvas: HTMLElement; public uiManager: UiManager; private assetsLoaded:boolean; // // constructor constructor(options: IEngineOptions) { this.loader = Loader.shared; this.renderer = new Renderer(options); this.world = new Container(); this.graphics = new Graphics(); this.fpsMax = options.fpsMax; /// * UI Manager * this.uiManager = new UiManager(true); this.canvas = options.containerId ? document.getElementById(options.containerId) || document.body : document.body; this.canvas.appendChild(this.renderer.view); /// /// Loader Setup /// this.loader.onComplete.add(() => { this.assetsLoaded = true; console.log("Assets Loader State:" + this.assetsLoaded); }) this.loader.load(); this.render(); } get view(): HTMLCanvasElement { return this.renderer.view; } public render(){ while (this.assetsLoaded = false) return; console.log(utils.TextureCache); let tmpWorld = new Container(); this.world.addChild( this.uiManager.getUI(), <<-- Render Fine and returns the Ui Container ); } } // Engine Edited May 5, 2021 by Teckniel typo Quote Link to comment Share on other sites More sharing options...
Exca Posted May 6, 2021 Share Posted May 6, 2021 The scope of the event handler function is incorrect. You can either bind the function to be in the scope of the class or use an arrow function to get the same effect. So doing the callback like: private onButtonClick = () :void => { console.log("clickt on button"); let btnTest = this.createMenuButton(); // <<-- Error: this.createMenuButton is not a function console.log(this.uiContainer); // <<-- Error: Undefined this.uiContainer //Launch a event to show a sprite... } Would fix it. Quote Link to comment Share on other sites More sharing options...
Teckniel Posted May 6, 2021 Author Share Posted May 6, 2021 (edited) 2 hours ago, Exca said: The scope of the event handler function is incorrect. You can either bind the function to be in the scope of the class or use an arrow function to get the same effect. So doing the callback like: private onButtonClick = () :void => { console.log("clickt on button"); let btnTest = this.createMenuButton(); // <<-- Error: this.createMenuButton is not a function console.log(this.uiContainer); // <<-- Error: Undefined this.uiContainer //Launch a event to show a sprite... } Would fix it. Thanks that fixed it. Now i use the arrow function to assign it to the local methode. // = () : void => What is the other option you describe. Pretty new to javascript and pixi. I'm primarly a .Net Developer gitting into typescript,but javascript is pain in the ass ;0 Thanks to provide a fix tho! Edited May 6, 2021 by Teckniel typo Quote Link to comment Share on other sites More sharing options...
Exca Posted May 6, 2021 Share Posted May 6, 2021 In javascript the scope of the function depends on how it's executed. For example if you have a class and you call it by myClass.foobar() then that is executed in the scope of the class. But if would do something like var func = myClass.foobar; func(); it would execute outside of the classes scope. Basically same thing happens when the event handler is run as you pass the info about the function only and not the scope. Old way of doing this was that you would do something like this: var that = this; function handler( ){ that.foobar(); } window.addEventListener("something", handler); More modern solution that came to be was to bind the function you give as parameter: class Foo { constructor(){ window.addEventListener("something", this.handler.bind(this)); } function handler { this.doSomething() } } And if you had to remove the listener at some point then first binding and assigning that to a variable and then passing that variable to listener would be way to go. With typescript I use nowadays purely arrow functions when there's scoping involved. Though they also have their drawbacks. Teckniel 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.