skip to Main Content

I have recently discovered an issue where I am not allowed to pass an object parameter to an onclick() method.

I did some research and it seems to be a popular issue. I have read this:
javascript: pass an object as the argument to a onclick function inside string
and I tried to stringify the object before passing to an onclick() but that does not seem to work.

enter image description here

My code:

        var object_info= {
            TypeID:11000,
            TypeValue:5,
            ValueID:12103,
            ValueValue:15,
            CorrectionID:11020,
            CorrectionValue:0,
            LabelStr:Analog_input_name[11000],
            TypeStr:InputATypeStr[5],
            DivId:"Test123",
        };

        Append_html_block(object_info);

The Append_html_block function:

function Append_html_block(object) {
    var generated_html = document.getElementById("custom_DIV");
    var stringifiedObj = JSON.stringify(object);

    generated_html .innerHTML += `
    <table class="sensor-values-table">
        <tr>
        <td class="top-item" style="width:90%;">${object.LabelStr}</td>
            <td>
                <button style="border:none;background-color:inherit;" onclick="Expand_selection(${stringifiedObj})">
       
                </button>
            </td>
        </tr>

    </table>
<br>
`;
}

The logic is very simple:
I create an object which I pass to Append_html_block function. Inside this function, I have a button. If this button is clicked, I want to perform specific actions and in order to do these actions I must know all the information about the object so I need to pass the object variable.

I didin’t manage to find a clear and simple solution for passing an ojbect variable to onclick(). Perhaps someone can suggest a neat and clean method for doing that? Thanks in advance!

3

Answers


  1. From an answer to the similar question you linked to, try using the encodeURIComponent function on the returned value from JSON.stringify and then where the object is needed, do the reverse process: use the JSON.parse function on the returned value of the decodeURIComponent function:

    function Append_html_block(object) { // try appendHtmlBlock instead (Camel Case
        var generated_html = document.getElementById("custom_DIV");
        var encodedObj = encodeURIComponent(JSON.stringify(object));
    
        generated_html .innerHTML += `
        <table class="sensor-values-table">
            <tr>
            <td class="top-item" style="width:90%;">${object.LabelStr}</td>
                <td>
                    <button style="border:none;background-color:inherit;" onclick="Expand_selection(${encodedObj})">
           
                    </button>
                </td>
            </tr>
    
        </table>
    <br>
    `;
    }
    

    and then in your Expand_selection function (which could be expandedSelection):

    function Expand_selection(encodedObject) {
      var object = JSON.parse(decodeURIComponent(encodedObject))
      console.log(object) // should work now
      // Do other stuff.
    }
    

    Hope this works out, let me know if it does :)👍

    answer reference: this answer by @João Pimentel Ferreira

    Login or Signup to reply.
  2. It is generally not a good idea to use inline event handlers.

    You can try handling the button using event delegation.

    Here is a minimal reproducable example of it.

    document.addEventListener(`click`, handle);
    const object_info = {
      TypeID: 11000,
      TypeValue: 5,
      ValueID: 12103,
      ValueValue: 15,
      CorrectionID: 11020,
      CorrectionValue: 0,
      LabelStr: `EXAMPLE-Analog_input_name[11000]`,
      TypeStr: `EXAMPLE-InputATypeStr[5]`,
      DivId: 'Test123',
    };
    
    Append_html_block(object_info);
    
    function handle(evt) {
      if (evt.target.dataset.expand) {
        evt.target.closest(`td`).querySelector(`pre`).classList.toggle(`hidden`);
      }
    }
    
    function Append_html_block(object) {
      var stringifiedObj = JSON.stringify(object, null, 2);
      document.querySelector(`#generated`).insertAdjacentHTML(`beforeend`,
        `<table class="sensor-values-table">
          <tr>
            <td>${object.LabelStr}</td>
            <td>
              <button data-expand="1">Expand/Hide</button>
              <pre class="hidden">${stringifiedObj}</pre>
            </td>
          </tr>
       </table>`);
    }
    .hidden {
      display: none;
    }
    
    td {
      vertical-align: top;
    }
    <div id="generated"></div>
    Login or Signup to reply.
  3. As I said in my comment you can use a unique ID (I used TypeID) to call the source object like:

    const objctInfo = [{
        TypeID: 11000,
        TypeValue: 5,
        ValueID: 12103,
        ValueValue: 15,
        CorrectionID: 11020,
        CorrectionValue: 0,
        LabelStr: 1,
        TypeStr: 5,
        DivId: "Test123",
      },
      {
        TypeID: 11001,
        TypeValue: 5,
        ValueID: 12103,
        ValueValue: 15,
        CorrectionID: 11020,
        CorrectionValue: 0,
        LabelStr: 2,
        TypeStr: 5,
        DivId: "Test124",
      },
    ];
    objctInfo.forEach(Append_html_block);
    
    function Append_html_block(obj) { 
        var generated_html = document.getElementById("custom_DIV");
    
        generated_html .innerHTML += `
        <table class="sensor-values-table" border=1>
            <tr>
            <td class="top-item" style="width:90%;">${obj.LabelStr}</td>
                <td>
                    <button style="border:none;background-color:inherit;" onclick="Expand_selection(${obj.TypeID})">
            click me
                    </button>
                </td>
            </tr>
    
        </table>
    <br>
    `;
    }
    
    function Expand_selection(id){
      const obj = objctInfo.find(obj => obj.TypeID === parseInt(id));
      console.log(obj);
    }
    <div id="custom_DIV"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search