0

I am trying to create js array with key = trener_id and values = selected service ID from the checked checkboxes

Whatever I do the array is being created but also there are many empty values that are being saved in the array. How to avoid this and finally to have a clean JS array with key trener_id and values only selected services IDs

Also is it possible and how to add sub-array that has Price customer and Price trener attached to each selected service value?

The php equivalent of the desired array format would be:

$trener_services = array(1){
[13]=>
  array(2) {
[47]=>array(2){
['Price_customer']=>
string(5) "10.00",
['Price_trener']=>
string(4) "5.00"
}
[45]=>array(2){
['Price_customer']=>
string(5) "60.00",
['Price_trener']=>
string(5) "10.00"
}
  }
}

Hope the question is clear.. Thanks for your time

var trener_services;

$('body').on('change', '.service_check', function() {
 trener_services = new Array();     
    $('.service_check:checked').each(function(){
    var sid = $(this).val();
    var trener_id = $(this).attr('data-trener');

    if(!trener_services[trener_id]){
    trener_services[trener_id] = [];
    }
  trener_services[trener_id].push($(this).val());
  console.log(trener_services);
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<table class="table table-hover table-striped text-left trener_service_table tren_ser_13">
<thead>
<tr>
<th class="text-left success">Select</th>
<th class="text-left success mw20">Service type</th>
<th class="text-left success">Price customer</th>
<th class="text-left success">Price trener</th>
</tr>
</thead>
<tbody><tr class="tren_ser_row_47"> 
<td><input id="service_check_47" data-trener="13" type="checkbox" class="service_check" value="47"></td>
<td><label for="service_check_47">Single play</label></td>
<td><input data-id="47" id="trener_client_price_47" class="short client_price client_price_47" type="text" value="10.00"></td>
<td><input data-id="47" id="trener_bonus_price_47" class="short bonus_price_47" type="text" value="5.00"></td>
</tr>
<tr class="tren_ser_row_45">    
<td><input id="service_check_45" data-trener="13" type="checkbox" class="service_check" value="45"></td>
<td><label for="service_check_45">Double play</label></td>
<td><input data-id="45" id="trener_client_price_45" class="short client_price client_price_45" type="text" value="60.00"></td>
<td><input data-id="45" id="trener_bonus_price_45" class="short bonus_price_45" type="text" value="10.00"></td>
</tr>
<tr class="tren_ser_row_46">    
<td><input id="service_check_46" data-trener="13" type="checkbox" class="service_check" value="46"></td>
<td><label for="service_check_46">Triple play</label></td>
<td><input data-id="46" id="trener_client_price_46" class="short client_price client_price_46" type="text" value="50.00"></td>
<td><input data-id="46" id="trener_bonus_price_46" class="short bonus_price_46" type="text" value="10.00"></td>
</tr>
</tbody>
</table>
Europeuser
  • 934
  • 1
  • 9
  • 32
  • 2
    you have a `var trener_services = ... ` inside your eventhandler. This is totaly unrelated the global `var trener_services = ...` you define outside of the eventhandler. Ie, everything you do with `trener_services` inside your eventhandler does not affect the global variable at all... – derpirscher Feb 15 '23 at 09:54
  • 1
    If you are creating an array with numeric index, the gaps will be automatically filled with empty values; instead you could [use an object to have numeric keys](https://stackoverflow.com/questions/2002923/using-an-integer-as-a-key-in-an-associative-array-in-javascript). You can then use `Object.keys(...)`, `Object.values(...)` and `Object.entries(...)` to retrieve the contents as shown [here](https://www.javascripttutorial.net/object/convert-an-object-to-an-array-in-javascript/) – SaschaM78 Feb 15 '23 at 09:57
  • @derpirscher that was copy/paste error – Europeuser Feb 15 '23 at 10:05
  • You made it worse... Now you don't have a global variable at all, so you're just throwing away the result of running your function every time... – Michael G Feb 15 '23 at 10:10
  • The simplest fix would be to have a global `var trener_services;` outside your eventhandler and then `trener_services = new Array();` (ie without `var`) inside your eventhandler. So you recreate the whole array every time, a check status changed. Or have a look at @MichaelG answer which uses an object instead of an sparse array – derpirscher Feb 15 '23 at 10:30
  • @derpirscher I changed the code as suggested but still prints many undifined in the array which was explained very well from SaschaM78 – Europeuser Feb 15 '23 at 10:36
  • Yeah, thats the nature of a sparse array. You are only filling specific indexes, all others are undefined ... Using an object is definitively the better way – derpirscher Feb 15 '23 at 10:51

1 Answers1

1

As one commenter suggested, you must use an Object instead of an Array. (Your trener_id is a string, not a number, unless JQuery automatically converts strings to numbers; I don't use JQuery so I wouldn't know.)

//this is a global variable so you can use it elsewhere
let trener_services;

document.body.addEventListener( "change", () => {

    trener_services = Object.fromEntries(
        //get all the checked services:
        [ ...document.querySelectorAll('.service_check:checked') ].
            //map them to object entries of the form [ key, value ]
            map( checkboxElement => [

                //key: the data-trener attribute
                //checkboxElement.getAttribute( "data-trener" ),

                //key: the checkbox's value field
                checkboxElement.value,

                //value: an array of the checkbox's value as well as the two sibling values you wanted
                [
                    checkboxElement.value,
                    document.querySelector( "#trener_client_price_" + checkboxElement.value ).value,
                    document.querySelector( "#trener_bonus_price_" + checkboxElement.value ).value
                ]

            ] )
    );

    console.log( trener_services );

})

Here is the same function, without the sub-array you requested. (Your question was very unclear, but I am trying my best.)

//this is a global variable so you can use it elsewhere
let trener_services;

document.body.addEventListener( "change", () => {

    trener_services = Object.fromEntries(
        //get all the checked services:
        [ ...document.querySelectorAll('.service_check:checked') ].
            //map them to object entries of the form [ key, value ]
            map( checkboxElement => [

                //key: the data-trener attribute
                //checkboxElement.getAttribute( "data-trener" ),

                //key: the checkbox's value field
                checkboxElement.value,

                //value: only the checkbox's value
                checkboxElement.value

            ] )
    );

    console.log( trener_services );

})
Michael G
  • 458
  • 2
  • 9
  • I created jsfiddle : https://jsfiddle.net/w5qor2pn/ and disovered that your code prints each service in separate array, but not all 3 for example in 1 array.. Am I right? – Europeuser Feb 15 '23 at 10:32
  • As you asked, "is it possible and how to add sub-array that has Price customer and Price trener attached to each selected service value". I will add a second copy that does not do that, I suppose? – Michael G Feb 15 '23 at 10:34
  • Your changed code prints just the last selected checkbox, but not all selected. Please allow me a minute to create the desired array format which may help you to understand my question. I agree the question is not well /clear asked – Europeuser Feb 15 '23 at 10:41
  • I edited my question and added php equivalent of the desired array format with trener #13 selected services, but there will be more than 1 trener selected at once.. – Europeuser Feb 15 '23 at 10:53
  • Michael G: After I runned some tests your first code can do the job I need and thats why I accepted your answer as correct ! Thank you very much for your time all of you guys ! – Europeuser Feb 15 '23 at 11:04
  • Are you trying to use this information in PHP? Unfortunately, I don't think I have enough experience with PHP to help (I've never used PHP arrays). I don't even know how you're sending this to your server... but whatever format you use, you'll have to somehow extract and convert it on the other end, using a function written in PHP. Sorry, maybe someone else can answer. – Michael G Feb 15 '23 at 11:05
  • Michael G sorry for bringing this to your attention again but I discovered that when I select 2 services for example the array if full with the last selected service details, not all selected.. Can this be fixed? – Europeuser Feb 15 '23 at 16:08
  • @Europeuser since you decided to use "data-trener" as your key, and it is the same for all services (13), they overwrite each other. (Just like in an array, only 1 data can be in slot 13. Add data to slot 13 again, and you will overwrite/erase whatever was there before). You will need to use a unique key, instead of "data-trener". Looking at your PHP array, I think you wanted to use the checkbox value? (Maybe?) I'll update the code, but if you aren't sure what you want... You might not get it. – Michael G Feb 16 '23 at 10:47