1

This question is similar to THIS ONE, but I still could not solve my issue after reading.

Basically I am trying to make the table below dynamic in size. Also, when a value is changed, I want it to update the underlying JavaScript function. enter image description here

**However I can't figure out how to both reference the elements uniquely and also pass the relevant parameters through to update the object. updatePlanner() is called upon a change, but the the value passed through is always the last unique ID created: in this case "2-11". What am I doing wrong? **

Here is my initial object:

builerObj.dataArray = [4,3,[[[5, .65, 0],[5, .75, 0],[5, .85, 1]], 
                            [[3, .70, 0],[3, .80, 0],[3, .90, 1]],
                            [[5, .75, 0],[3, .85, 0],[1, .95, 1]],
                            [[5, .40, 0],[5, .50, 0],[5, .60, 0]]]];

Here is the function to update it (Notice that I pass through the Id of an element to reference its value):

function updatePlanner(passedId, week, set, index) {
    var value = document.getElementById(passedId).value;

    // I've removed some irrelevant manipulation of the value variable

    builerObj.dataArray[2][week][set][index] = value;

        columns = $('#planBuilderWeeks')[0].value; // columns
        rows = $('#planBuilderSets')[0].value; // rows
        createPlanningTable(columns, rows);

}

And here is the table generator (styling code removed):

function createPlanningTable(columns, rows){
    var body = document.getElementById('planBuilderTable'),
        tbl  = document.createElement('table');

    // Styling and Headers are here

    for(var i = 0; i < rows; i++){
        var tr = tbl.insertRow();
        var week = 0;

        for(var j = 0; j < columns * 3; j++){
            var td = tr.insertCell();
            var currID = i.toString() + "-" + j.toString(); // Unique ID for each input

            if (j % 3 == 0 ){              // This handels all columns labeled '%Max'
                var currItem = document.createElement('input');
                currItem.value = builerObj.dataArray[2][week][i][0];
                currItem.addEventListener("change", function(){
                     updatePlanner(currID, week, i, 0); // This is where I haven't been able to make it work
                }, false);
            } else if (j % 3 == 1){        // This handels all columns labeled 'Reps'
                var currItem = document.createElement('input');
                currItem.value = builerObj.dataArray[2][week][i][1];
            } else if (j % 3 == 2){        // This handels all columns labeled '+'
                var currItem = document.createElement('button');
                currItem.style.display = "block";
                var span = document.createElement('span');
                if (builerObj.dataArray[2][week][i][2] == 1){
                    span.className = "glyphicon glyphicon-ok box";
                } else{
                    span.className = "glyphicon box";
                }
                currItem.appendChild(span);
                week += 1;
            } else {
                alert("Something went wrong");
            }

            currItem.setAttribute("id", currID);   
            td.appendChild(currItem);
        }
    }
    body.innerHTML = "";
    body.appendChild(tbl);
}

2 Answers 2

1

currID is evaluated at the moment the listener is executed. At that moment, currID has already reached its last value. Instead of passing the id, you can pass the value to updatePlanner, like this:

function updatePlanner(value, week, set, index) {

and then the call is:

updatePlanner (this.value, week, i, 0);

But note, that 'week' and 'i' have also already reached their last values. I noticed that you are using JQuery in the updatePlanner function. JQuery's ".on" function can remember the right values for you. Here is the solution:

         if (j % 3 == 0 ){ 
             var currItem = document.createElement('input');
             var eventData = { week : week, set : i };
             $(currItem).on("change", null, eventData, function(event){
                 updatePlanner(event.target.value, event.data.week, event.data.set, 0);
             });
Sign up to request clarification or add additional context in comments.

4 Comments

@www.admiaalit.nl YES! thank you so much! This is my first major JavaScript creation. Would you say that this is a bad design? If so how else can I build this functionality?
I have changed my answer by using JQuery
Personally, I would have used AngularJS. This would eliminate the need to create HTML tags in JavaScript. Instead, you would use so-called 'directives' in the HTML page to dynamically build the table. But there are other frameworks that have similar functionality.
I have just learned about parameter 'data' of JQuery's ".on" function, which simplifies the solution. For more info, see api.jquery.com/on
1

You could also use Closures, so you would not need to alter your HTML.

function updatePlannerEvent( currId, week, i ) {
    return function() {
        updatePlanner(currId, week, i, 0);
    }
}

currItem.addEventListener("change", updatePlannerEvent(currId, week, i), false);

Comments

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.