1

Here is what we're trying to do:

$(document).ready(function()
      {
          for (var i = 0; i < 10; i++)
          {
              for (var j = 0; j < 15; j++)
              {
                  $('#Row'+(i+1)+'Sub' + (j+1) + '_ClientDropDown').ready(function() 
                       { TrimServices_Function( "Row" + (i+1) + "_Sub" + (j+1).ToString() + "_ClientDropDown"); })

              }
          }
     })

Unfortunately, Javascript doesn't really pass the i and j into the second function correctly. When doing alerts in other tests it creates a line with the right initial call, but then the other part just returns 10 and 15. So lets say line 5 sub 7 would be:

$('#Row5Sub7_ClientDropDown').ready(function() 
    { TrimServices_Function( "Row11_Sub16_ClientDropDown"); })

How would we go about making sure that we loop through lines where the row and sub match up?

Freeman
  • 41
  • 6
  • 1
    It's working correctly. You're creating a closure on variables that change their values each time through the loops. So the value of those variables when the function later executes is capturing the final value of those variables, rather than the value at the time the function was passed to ready(). That IS the correct behavior for closures. – RJM Apr 26 '17 at 02:13
  • Here's an answer to this problem: http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – RJM Apr 26 '17 at 02:14
  • Replace `var` in your for loops with `let`. –  Apr 26 '17 at 02:31
  • What's that jQueryElement.ready for? Just use a closure. – StackSlave Apr 26 '17 at 02:33
  • @torazaburo, let (and const) won't work in older browsers, so usage of those will depend on whether you have to support them or not. – jfren484 Apr 26 '17 at 02:38
  • 1
    @jfren484 Valid point, but at this point in the history of the world, JS programmers should be working in an environment where they are able to write ES6. If they need to support browsers that don't support it, then they need to organize a transpilation environment for themselves. Long ago we stopped calling out ES5 dependencies such as `forEach` in SO answers, even though they don't work in IE8; we now no longer call out ES6 dependencies, even though they don't always work in IE11. Actually `let` **does** work in IE11, the only currently supported version of IE. –  Apr 26 '17 at 03:02
  • @torazaburo, I wasn't saying we shouldn't mention newer features and recommend them. I'm merely saying that you shouldn't direct someone to start using them without giving them that caveat. If you had said, "If you're targeting ES6 browsers and higher, replace var with let," I would have had no issue with your comment. – jfren484 Apr 26 '17 at 13:29
  • And "JS programmers should be working in an environment where they are able to write ES6" is irrelevant. I *should* be able to take advantage of any new features that are invented in programming, but at most places I've worked, there was some degree of lag (some more, some less). Browser support requirements will vary a lot based on what kind of application you're working on, and it's not uncommon for applications to have to support browsers like IE 10 or even older. The fact that IE 10 and below are unsupported doesn't mean they aren't used in some very large organizations. – jfren484 Apr 26 '17 at 13:35
  • I did not say to not support IE10 (although a wise organization would not choose to). I said to program in a modern fashion where you are able to write programs in a modern way. Yes, that may require an ES6 toolchain. Virtually all competent development shops, large and small, do that. –  Apr 26 '17 at 16:11

1 Answers1

1

Set both strings outside of the function inside the second for loop like this (I would also clean up your string concatenation, but I left it as you had it here):

      for (var i = 0; i < 10; i++)
      {
          for (var j = 0; j < 15; j++)
          {
              var selectorA = '#Row'+(i+1)+'Sub' + (j+1) + '_ClientDropDown';
              var selectorB = "Row" + (i+1) + "_Sub" + (j+1).ToString() + "_ClientDropDown";

              $(selectorA).ready(function() 
                   { TrimServices_Function(selectorB); })

          }
      }
jfren484
  • 960
  • 10
  • 13
  • 1
    Other recommendations - instead of looping from 0 to 9 or 14 and then adding 1 to i and j every time, loop from 1 to 10 and 15, respectively. It would be much cleaner. And pick single or double quotes and go with it. Don't switch back and forth. – jfren484 Apr 26 '17 at 02:18
  • Did you check this to make sure it works? I think by the time the internal function is called, `selectorB` will already have its last value. –  Apr 26 '17 at 02:30
  • Yep, it works: https://jsfiddle.net/jfren484/z8q8rud0/ – jfren484 Apr 26 '17 at 02:36