0

I have the following code to populate a hidden field after a change or a keydown event for any form field on each input row:

$(".leave_row_0").bind("keydown change", function(e) {
  $(".leave_hidden_0").val("1");
});

$(".leave_row_1").bind("keydown change", function(e) {
  $(".leave_hidden_1").val("1");
});

$(".leave_row_2").bind("keydown change", function(e) {
  $(".leave_hidden_2").val("1");
});

However, I will not know the total number of rows that will appear on the page at any given one time, so I need to write this dynamically. I have written a for loop to simplify things, but for some reason the code stops working when I try to execute it this way:

var k = 0;
for (k = 0; k < leave_requests.length; k++) {
  $(".leave_row_" + k).bind("keydown change", function(e) {
    $(".leave_hidden_" + k).val("1");
  });
}

Any ideas about an extra ingredient that I might be missing?

Here is my html structure:

i = 0;
                    json[2].forEach(function(leave){
                        leave_requests.push(
                            '<div class="row">' +
                                '<div class="col-sm-2 low-padding-right">' +
                                    '<input type="text" value="' + format_date(json[2][i]['leave_date'], 'leave') + '" name="leave_date[]" class="leave_row_' + i + ' form-control" readonly>' +
                                '</div>' + 
                                '<div class="col-sm-1 low-padding">' +
                                    '<select class="leave_row_' + i + ' form-control" name="day_part[]" id="day_part" style="width: 100%;">' +
                                        '<?php foreach($dayparts as $daypart){ ?>' +
                                            '<option value="{{ $daypart->daypart_id }}">{{$daypart->daypart}}</option>' +
                                        '<?php } ?>' +
                                    '</select>' +
                                '</div>' +
                                '<div class="col-sm-1 low-padding">' +
                                    '<select class="leave_row_' + i + ' form-control" name="leave_type[]" id="leave_type" style="width: 100%;">' +
                                        '<?php foreach($leave_types as $leave_type){ ?>' +
                                            '<option value="{{ $leave_type->leave_type_type_id }}">{{ $leave_type->leave_type_type }}</option>' +
                                        '<?php } ?>' +
                                    '</select>' +
                                '</div>' +
                                '<div class="col-sm-4 low-padding">' +
                                    '<input type="text" value="' + filter_null_values(json[2][i]['leave_notes']) + '" name="leave_notes[]" class="leave_row_' + i + ' form-control">' +
                                '</div>' +
                                '<div class="col-sm-1 low-padding">' +                            
                                    '<input type="text" value="' + (json[2][i]['employee_first_name']).charAt(0) + json[2][i]['employee_last_name'] + '" name="last_updated[]" class="leave_row_' + i + ' form-control" readonly>' +
                                '</div>' +
                                '<div class="col-sm-2 low-padding">' +            
                                    '<input type="text" value="' + format_date(json[2][i]['leave_updated_time'], 'updated') + '" name="leave_updated_time[]" class="leave_row_' + i + 'form-control" readonly>' +
                                '</div>' +
                                '<div class="col-sm-1 low-padding">' +
                                    '<select class="form-control" class="leave_row_' + i + ' name="status[]" id="status" style="width: 100%;">' +
                                        '<?php foreach($status_names as $name){ ?>' +
                                            '<option value="' + json[2][i]['status_name'] + '" name="status" class="form-control">' + json[2][i]['status_name'] + '</option>' +
                                        '<?php } ?>' +
                                    '</select>' +
                                '</div>' +
                            '</div>' +
                            '<input type="hidden" value="" name="leave-hidden" class="leave_hidden_' + i + ' form-control" readonly>'                           
                        );

                        i++;
                    });
Robert Young
  • 523
  • 1
  • 8
  • 22
  • 2
    Possible duplicate of [JavaScript closure inside loops – simple practical example](https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – VLAZ Oct 14 '19 at 10:20
  • 3
    `bind()` is depreciated since 3.0. You might want to consider using `on()`. Also please post your corresponding html code too. – Mark Baijens Oct 14 '19 at 10:20
  • 1
    This can be solved with a closure (as @VLAZ's comment suggests) however a much better idea entirely is to get rid of the incremental classes and the loop you're using. Instead, use a common class on all the `.leave_row` elements, then use DOM traversal to find the related `.leave_hidden` element, and update its `val()`. If you'd like an example of how to do this, please add your HTML to the question – Rory McCrossan Oct 14 '19 at 10:35

3 Answers3

0

You can select all rows which has className starts with leave_row_, loop through and bind your events for each row. Since hidden fields and row will have same numeric suffix, split that out and do the rest

$("[class^=leave_row_]").each(function(i, elem) {
   $(`.${elem.className}`).bind("keydown change", function(e) {
        $(".leave_hidden_"+e.target.className.split('_')[2]).val("1");
   });
})

Instead using bind which is deprecated on is used in below demo. Just for demo type="hidden" is type="text"

$("[class^=leave_row_]").each(function(i, elem) {
   $(`.${elem.className}`).on("keydown change", function(e) {
        //console.log(e.target.className);
        $(".leave_hidden_"+e.target.className.split('_')[2]).val("1");
   });
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<input type="text" class="leave_row_0"></input>

<input type="text" value="0_hidden" class="leave_hidden_0"></input> 

<input type="text" class="leave_row_1"></input>

<input type="text" value="1_hidden" class="leave_hidden_1"></input>
Bilal Siddiqui
  • 3,579
  • 1
  • 13
  • 20
0

Use a common class instead of incrementing a number with class in both the cases leave_row and leave_hidden. No need to use loop even you can use 'this' Plz check below I am not sure if you have hidden field already present in DOM or not, as you are creating leave_row you must be having leave_hidden present in the DOM

$(".leave_row").bind("keydown change", function(e) {
 $(this).siblings('.leave_hidden').val(1);
});
  • class name is not just `leave_row` but it has a numeric suffix for each row – Bilal Siddiqui Oct 14 '19 at 10:48
  • @Robert Young If possible can you show your HTML structure. – pramukh kulshrestha Oct 14 '19 at 10:49
  • @BilalSiddiqui exactly, that's the point of this answer; to avoid ugly hacking around of strings using `split('_')` etc – Rory McCrossan Oct 14 '19 at 11:04
  • @RoryMcCrossan I thought we need to give solution to current problem first. Also its better to suggest improvement. This is not an answer but suggesstion. – Bilal Siddiqui Oct 14 '19 at 11:08
  • Sometimes it becomes impossible to modify the current system. Specially with those rows which comes auto-generated from a thrid-party js files. I ran with such problems using jquery.colorbox.js many times. – Bilal Siddiqui Oct 14 '19 at 11:10
  • That I agree with, which is why I suggested this solution in the comments as right now it's too great an assumption (in terms of whether the OP can modify the HTML, and also the structure of that HTML) to be a workable answer. – Rory McCrossan Oct 14 '19 at 11:13
0

Don't worry, I have kind of solved it for now using siblings and traversing the DOM element, so Pramukh's answer was partly correct:

json[2].forEach(function(leave){
                        leave_requests.push(
                            '<div class="row">' +
                                '<div class="col-sm-2 low-padding-right">' +
                                    '<input type="text" value="' + format_date(json[2][i]['leave_date'], 'leave') + '" name="leave_date[]" class="leave_row form-control" readonly>' +
                                '</div>' + 
                                '<div class="col-sm-1 low-padding">' +
                                    '<select class="leave_row form-control" name="day_part[]" id="day_part" style="width: 100%;">' +
                                        '<?php foreach($dayparts as $daypart){ ?>' +
                                            '<option value="{{ $daypart->daypart_id }}">{{$daypart->daypart}}</option>' +
                                        '<?php } ?>' +
                                    '</select>' +
                                '</div>' +
                                '<div class="col-sm-1 low-padding">' +
                                    '<select class="leave_row form-control" name="leave_type[]" id="leave_type" style="width: 100%;">' +
                                        '<?php foreach($leave_types as $leave_type){ ?>' +
                                            '<option value="{{ $leave_type->leave_type_type_id }}">{{ $leave_type->leave_type_type }}</option>' +
                                        '<?php } ?>' +
                                    '</select>' +
                                '</div>' +
                                '<div class="col-sm-4 low-padding">' +
                                    '<input type="text" value="' + filter_null_values(json[2][i]['leave_notes']) + '" name="leave_notes[]" class="leave_row form-control">' +
                                '</div>' +
                                '<div class="col-sm-1 low-padding">' +                            
                                    '<input type="text" value="' + (json[2][i]['employee_first_name']).charAt(0) + json[2][i]['employee_last_name'] + '" name="last_updated[]" class="leave_row form-control" readonly>' +
                                '</div>' +
                                '<div class="col-sm-2 low-padding">' +            
                                    '<input type="text" value="' + format_date(json[2][i]['leave_updated_time'], 'updated') + '" name="leave_updated_time[]" class="leave_row form-control" readonly>' +
                                '</div>' +
                                '<div class="col-sm-1 low-padding">' +
                                    '<select class="form-control" class="leave_row" name="status[]" id="status" style="width: 100%;">' +
                                        '<?php foreach($status_names as $name){ ?>' +
                                            '<option value="' + json[2][i]['status_name'] + '" name="status" class="form-control">' + json[2][i]['status_name'] + '</option>' +
                                        '<?php } ?>' +
                                    '</select>' +
                                '</div>' +
                            '</div>' +
                            '<input type="hidden" value="" name="leave-hidden" class="leave_hidden form-control" readonly>'                           
                        );

                        i++;
                    });

$(".leave_row").bind("keydown change", function(e) {
                    $(this).parent().parent().next('.leave_hidden').val(1);
                });
Robert Young
  • 523
  • 1
  • 8
  • 22