0

Frontend I can access methods of an instance of a class by static code:

instanceName.method(varValue);

The class is Gauge (library SVG Gauge) and with the above code I can control the pointer of my instanced gauge as expected. I can also control it with pre-render generated code in EJS:

<%= gaugeInstanceVar %>.setValue(<%= gaugeValueVar %>);

But I am getting a variable in through Server Sent Events after rendering and gaugeInstanceVar, containing the name of the instance used thus:

gaugeInstanceVar.method(varValue) throws: Uncaught TypeError: X.setValue is not a function.

It also feels wrong to me, like failing to modify my variable, when I really want to use the value to call the instance.

What however would be the correct way of accessing the method (in my current case ".setValue()" of an active instance of a Class, using the variable gaugeInstanceVar?

Edit:

Using eval() would also achieve the desired effect

eval(sseTopic).setValue(sseValueNumber);

But I believe I should stay away from it and am still looking for the correct way of achieving the equivalent.

Edit 2 (feedback for Bergi)

I have condensed the code down to one if the 7 gauge types, here switch case 3.

The user input is just via form, everything apart from the code below is handled backend.

The library "SVG Gauges" takes the var to create the instance of Gauge. The divs with corresponding id's are created one step earlier - I don't think we need that code here.

EJS provides element.topic for the var, as well as the id, which is desired.

<%
data.forEach( element=> {

switch(element.gaugetype) {

case 'gauge3':
gaugeClass ='gauge-container three'; // used for div's
%> 
<script>var <%= element.topic %> = Gauge(document.getElementById('<%= element.topic %>'), {
max: <%= element.value %>,
value: 50
} );</script>
<%
break;

default:
return;
break;
} %>

After removeSpecialCharacters(string) the variable sseTopic in the code below is identical with element.topic in the code above.

  //Server Sent Event-Handler
  let sse = new EventSource("http://localhost:3000/sse-stream");

    sse.onmessage = function (event) {
    let jdata = JSON.parse(event.data);

    let sseValue = jdata.message;
    let sseValueNumber = Number(sseValue);

    let rawSseTopic = jdata.topicname;
    let sseTopic = removeSpecialCharacters(rawSseTopic);

    sseTopic.setValue(sseValueNumber); // Type ERROR not a function

    // eval(sseTopic).setValue(sseValueNumber);    not desirable b
  };

  function removeSpecialCharacters(string) {
    let cleanString = string.replace(/,|\.|-|_|\|\s|\//g, "");
    return cleanString;
  }
7
  • 1
    Possible duplicate: "Variable" variables in JavaScript et al. The best way to deal with this is to either store the instance in a wrapper object (const instances = { [yourInstanceNameHere]: { /* ... */ } }) or refactor your code so that you won't have to refer to your variables using their names. Commented May 7, 2023 at 5:40
  • I am probably missing something here and will delve more into Classes before I continue. I was not able to derive my solution from the suggested answer. So you are saying I should create that wrapper object while the instances are created (forEach loops), so that I can call methods later. Commented May 7, 2023 at 15:45
  • @DegreeInNoobology No, you should not create wrapper objects. And the question seems to be not about calling dynamic methods by name, but rather about accessing instances by name. The solution to that is to not go by variable names but rather to put all of the instances that you want to access into a collection where you can look them up. Commented May 7, 2023 at 16:30
  • TY for getting back. I have no static list of instances. Users can add gauges to their dashboard and the server will send live data accordingly. If the user has created a gauge called "factory/machines/machine201/temperature" the code removes certain chars and names an instance accordingly. The message coming in contains the same name that I need to use for setting a new value. Can I update that collection dynamically? Commented May 7, 2023 at 22:39
  • Yes, you can and should (need to) update the list dynamically. Please show us the code that is adding the gauge to a user's dashboard (derives the name, updates the SSE, creates the new instance of the gauge, adds it to the DOM) if you need help with this Commented May 7, 2023 at 22:47

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.