0

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!

TheBestPlayer
  • 324
  • 2
  • 13

3 Answers3

1

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>
KooiInc
  • 119,216
  • 31
  • 141
  • 177
  • `` — This seems like something far better suited to a `data-*` attribute. The JSON isn't going to be displayed raw to the user is it? – Quentin Jul 12 '23 at 10:08
0

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>
Simone Rossaini
  • 8,115
  • 1
  • 13
  • 34
  • Please can you clarify my few concerns regarding this method: 1. This method will only work if the object is declared globally (need to ensure expand_selection method have access to the object). 2. Additionally, what would happen if I have multiple objects for example objcetInfo1, objectInfo2, objectInfo3 and etc...? – TheBestPlayer Jul 12 '23 at 10:28
  • 1. Yes (just use a variable `let`) 2. Just group all object in one array like my example – Simone Rossaini Jul 12 '23 at 10:36
-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

Izebeafe
  • 182
  • 1
  • 4
  • I have tested it out and it seem to work :) Is there any particular reason why javascript is being so weird about passing object to onclick function? – TheBestPlayer Jul 12 '23 at 10:23
  • No idea, but I do most of my projects with react js and I don't often have these kind of issues. Maybe cause everything is basically JavaScript, so all that stringify - parse gist isn't really necessary for passing arguments like that ‍♂️ – Izebeafe Jul 12 '23 at 14:16