简体   繁体   中英

How to declare onclick function in HTML property in TypeScript?

First time asking question here.

Can someone help me in declaring dynamic onclick function in HTML property inside forEach function using TypeScript ?

By the way, i am new in typescript. hehe.

Here is my old code that i want to convert in TypeScript:

const MyClass = (() =>
{
    let this_MyClass = {};

    this_MyClass.load = () =>
    {
        let tr;
        $.each(data, function()
        {
            tr += 
                `<tr>
                    <td><button onclick = "MyClass.set_id(${this.id})">Edit</button></td> 
                </tr>`;
         }
         $("#table_id tbody").html(tr);
    };

    this_MyClass.set_id = (id) =>
    {
        //my codes here
    };

    return this_MyClass;

})();

My new code in typescript(but its not working):

class MyClass
{

    load()
    {
        let tr:any;
        let iteration = 0;

        data.forEach((value:{id: number;}) =>
        {
            tr +=
               `<tr>
                   <td><button id="btn_edit${iteration}">Edit</button></td>
               </tr>`;

        document.getElementById(`btn_edit${iteration}`)?.addEventListener("click", 
            (e: Event) => this.set_id(value.id));

            iteration++;
        });
        $("#table_id tbody").html(tr);
    }

    set_id(id:number)
    {
        //my codes here
    }
}

can someone help me.

Code Update: location of " set_id " method

In the TS code you are adding event listener on the element which is not present in the DOM yet. First add the element into the DOM and then add event listener.

Working code:

class MyClass {
    load() {
       // let data = [{ id: 1 }, { id: 2 }, { id: 3 }] Adding for testing
        let tr: any;
        let iteration = 0;
        let trBtnIds = [];
        data.forEach((value: { id: number }) => {
            tr +=
                `<tr>
                   <td><button  id="btn_edit${iteration}">Edit</button></td>
               </tr>`;
            trBtnIds.push({
                iteration,
                value
            });
            iteration++;
        });
        $("#table_id tbody").html(tr);

        trBtnIds.forEach(item => {
            document.getElementById(`btn_edit${item.iteration}`) ?.addEventListener("click", (e: Event) => {
                this.set_id(item.value.id);
            });
        });

    }
    set_id(id: number) {
        console.log(id);
    }
}

/* Adding these line for testing */
//let myClassObject = new MyClass();
//myClassObject.load();

Babel compiled working code

 "use strict"; function _instanceof(left, right) { if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return !!right[Symbol.hasInstance](left); } else { return left instanceof right; } } function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var MyClass = /*#__PURE__*/ function () { function MyClass() { _classCallCheck(this, MyClass); } _createClass(MyClass, [{ key: "load", value: function load() { var _this = this; var data = [{ id: 1 }, { id: 2 }, { id: 3 }]; //Adding for testing var tr; var iteration = 0; var trBtnIds = []; data.forEach(function (value) { tr += "<tr>\\n <td><button id=\\"btn_edit".concat(iteration, "\\">Edit</button></td>\\n </tr>"); trBtnIds.push({ iteration: iteration, value: value }); iteration++; }); $("#table_id tbody").html(tr); trBtnIds.forEach(function (item) { var _document$getElementB; (_document$getElementB = document.getElementById("btn_edit".concat(item.iteration))) === null || _document$getElementB === void 0 ? void 0 : _document$getElementB.addEventListener("click", function (e) { _this.set_id(item.value.id); }); }); } }, { key: "set_id", value: function set_id(id) { console.log(id); } }]); return MyClass; }(); /* Adding these line for testing */ var myClassObject = new MyClass(); myClassObject.load();
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <table id="table_id"> <tbody> </tbody> </table>

Alternate approach:

Instead of creating event listener for each td button . Use javascript event bubbling technique. Listening to event for all td buttons is expensive.

Here is the example.

Create the event listener on the table or the wrapping element.

HTML

<table id="table_id">
</table>

Script

class MyClass {
    load() {
       // let data = [{ id: 1 }, { id: 2 }, { id: 3 }] /**Adding for testing */
        let tr: any;
        let iteration = 0;
        let trBtnIds = [];
        data.forEach((value: { id: number }) => {
            tr +=
                `<tr>
                   <td><button data-id="${value.id}" id="btn_edit${iteration}">Edit</button></td>
               </tr>`;
            trBtnIds.push({
                iteration,
                value
            });
            iteration++;
        });
        $("#table_id tbody").html(tr);

        let ele = document.getElementById('table_id');
        ele.addEventListener('click', event => {
            console.log(event.target);
            let target = event.target;
            if (target instanceof HTMLButtonElement && target.dataset && target.dataset.id) {
                let id = target.dataset.id;
                this.set_id(id);
            }
        });

    }
    set_id(id: number) {
        console.log(id);
    }
}

/**Adding for testing */
//let myClassObject = new MyClass();
//myClassObject.load();

Babel compiled working code

 "use strict "; function _instanceof(left, right) { if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return !!right[Symbol.hasInstance](left); } else { return left instanceof right; } } function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var MyClass = /*#__PURE__*/ function() { function MyClass() { _classCallCheck(this, MyClass); } _createClass(MyClass, [{ key: "load", value: function load() { var _this = this; var data = [{ id: 1 }, { id: 2 }, { id: 3 }]; /**Adding for testing */ var tr; var iteration = 0; var trBtnIds = []; data.forEach(function(value) { tr += "<tr>\\n <td><button data-id=\\"".concat(value.id, "\\" id=\\"btn_edit").concat(iteration, "\\">Edit</button></td>\\n </tr>"); trBtnIds.push({ iteration: iteration, value: value }); iteration++; }); $("#table_id tbody").html(tr); var ele = document.getElementById('table_id'); ele.addEventListener('click', function(event) { var target = event.target; if (_instanceof(target, HTMLButtonElement) && target.dataset && target.dataset.id) { var id = target.dataset.id; _this.set_id(id); } }); } }, { key: "set_id", value: function set_id(id) { console.log("ID:", id); } }]); return MyClass; }(); /**Adding for testing */ var myClassObject = new MyClass(); myClassObject.load();
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <table id="table_id"> <tbody> </tbody> </table>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM