Reputation: 65
Can't catch a click event on a button in typescript.
I have very simple set up: a button in index.html
and a short code that tries to detect whether or not the button was clicked, but it is not working. Here are these two files:
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Typescript App</title>
</head>
<body>
<div id="main" class="main">
<div id="display">
<button id="testSmth">Test Something</button>
</div>
</div>
<script src="./index.ts"></script>
</body>
</html>
And here is index.ts
:
console.log('Starting')
class TestSmth {
testSmthBut: HTMLObjectElement | null;
clicked: boolean;
constructor(){
this.testSmthBut = document.querySelector('#testSmth');
this.clicked = false;
this.testSmthBut?.addEventListener('click', this.clickHandler);
}
clickHandler = (): void => {
this.clicked = true;
console.log('clicked');
};
}
function sleep(milliseconds: number): void {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
function lookigForClick(foo: TestSmth): void {
if (foo.clicked === true) {
console.log('yehhhh!!!');
return;
}
else {
console.log('still waiting');
sleep(1000);
lookigForClick(foo);
}
}
console.log('A')
let testsmth = new TestSmth();
lookigForClick(testsmth);
After compiling to js
and starting a local server with node.js
I can't get the recursion to stop no matter how often I clicked the button (see image below). What do I do wrong? Thanks :)
EDIT:
-project_folder: ---tsconfig.json ---package.json ---src: ------index.ts ------index.html
npm install npm start
{ "name": "carcassone-parcel", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "parcel serve src/index.html", "watch": "parcel watch src/index.html" }, "author": "", "license": "ISC", "devDependencies": { "@typescript-eslint/eslint-plugin": "^4.11.0", "@typescript-eslint/parser": "^4.11.0", "eslint": "^7.16.0", "eslint-config-prettier": "^7.1.0", "eslint-plugin-prettier": "^3.3.0", "parcel": "^1.12.4", "parcel-bundler": "^1.12.4", "prettier": "^2.2.1", "typescript": "^4.3.5" } }
{ "compilerOptions": { "target": "es5", "module": "esnext", "lib": ["ESNext", "DOM"], "jsx": "react", "sourceMap": true, "strict": true, "moduleResolution": "node", "baseUrl": "./src", "paths": { "~/*": ["./*"] }, "typeRoots": ["src/images/"], "allowSyntheticDefaultImports": true, "esModuleInterop": true }, "include": ["src/**/*"] }
Upvotes: 0
Views: 1400
Reputation: 9923
The problem is that you've created an infinite loop. To make sense for you just run lookigForClick
method in playground and see the browser is hanging.
This is playground link that is hanging because of infinite loop.
Solution
Instead of custom infinite loop use setInterval
methods like this:
function lookigForClick(foo: TestSmth): void {
if (foo.clicked === true) {
console.log('yehhhh!!!');
return;
}
else {
console.log('still waiting');
}
}
console.log('A');
let testsmth = new TestSmth();
window.setInterval(()=>{
lookigForClick(testsmth)
},1000)
Here is StackBlitz working sample that I created for you.
Update
It seems you need custom infinite loop. So you have two options:
1.sleep methods must be async
to prevent browser freezing. Note that In this way you don't really wait for another action you just have working infinite loop.
function delay(ms: number) {
return new Promise( resolve => setTimeout(resolve, ms) );
}
And then use it in lookigForClick
methods like this:
function lookigForClick(foo: TestSmth): void {
if (foo.clicked === true) {
console.log('yehhhh!!!');
return;
}
else {
(async () => {
console.log('still waiting');
await delay(1000);
lookigForClick(foo);
})();
}
}
sleep(10000)
I have to wait 10 seconds to execute next line code!Again Note that your sleep method didn't actually wait. To test that just call sleep(10000)
and see immediately console.log('still waiting');
executed.
So to have actual wait method simply use window.setTimeout
like this:
function lookigForClick(foo: TestSmth): void {
if (foo.clicked === true) {
console.log('yehhhh!!!');
return;
}
else {
window.setTimeout(()=>{
console.log('still waiting');
lookigForClick(foo);
}, 10000);
}
}
Now run this Playground link and see after each 10 seconds this console.log('still waiting');
executed.
Upvotes: 1