Я пытаюсь создать массив js с ключом = trener_id и значениями = выбранным идентификатором службы из отмеченных флажков.
Что бы я ни делал, массив создается, но также есть много пустых значений, которые сохраняются в массиве. Как этого избежать и, наконец, иметь чистый JS-массив с ключом trener_id и значениями только выбранных идентификаторов сервисов
Также возможно ли и как добавить подмассив, в котором к каждому выбранному значению услуги прикреплены Price customer и Price trener?
PHP-эквивалент желаемого формата массива:
$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"
}
}
}
Надеюсь вопрос ясен.. Спасибо за ваше время
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.info(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>
Если вы создаете массив с числовым индексом, пробелы будут автоматически заполнены пустыми значениями; вместо этого вы можете использовать объект для цифровых клавиш . Затем вы можете использовать Object.keys(...), Object.values(...) и Object.entries(...) для извлечения содержимого, как показано здесь
@derpirscher, это была ошибка копирования/вставки
Вы сделали еще хуже... Теперь у вас вообще нет глобальной переменной, поэтому вы каждый раз просто отбрасываете результат выполнения своей функции...
Самым простым решением было бы иметь глобальный var trener_services; вне вашего обработчика событий, а затем trener_services = new Array(); (то есть без var) внутри вашего обработчика событий. Таким образом, вы пересоздаете весь массив каждый раз, когда меняется статус проверки. Или посмотрите ответ @MichaelG, в котором используется объект вместо разреженного массива.
@derpirscher Я изменил код, как было предложено, но по-прежнему печатает много неопределенностей в массиве, который очень хорошо объяснил SaschaM78.
Да, это природа разреженного массива. Вы заполняете только определенные индексы, все остальные не определены... Использование объекта определенно лучший способ
Как предложил один комментатор, вы должны использовать Объект вместо Массив. (Ваш trener_id — это строка, а не число, если только JQuery автоматически не преобразует строки в числа; я не использую JQuery, поэтому не знаю.)
//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.info( trener_services );
})
Вот та же функция, но без запрошенного вами подмассива. (Ваш вопрос был очень неясным, но я стараюсь изо всех сил.)
//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.info( trener_services );
})
Я создал jsfiddle: jsfiddle.net/w5qor2pn и обнаружил, что ваш код печатает каждую службу в отдельном массиве, а не все 3, например, в 1 массиве. Я прав?
Как вы спросили, «возможно ли и как добавить подмассив, в котором к каждому выбранному значению услуги привязаны цена клиента и цена тренера». Я добавлю вторую копию, которая этого не делает, я полагаю?
Ваш измененный код печатает только последний выбранный флажок, но не все выбранные. Пожалуйста, дайте мне минуту, чтобы создать нужный формат массива, который может помочь вам понять мой вопрос. Я согласен, что вопрос некорректен / четко задан
Я отредактировал свой вопрос и добавил php-эквивалент желаемого формата массива с выбранными сервисами trener # 13, но одновременно будет выбрано более 1 trener.
Майкл Г.: После того, как я провел несколько тестов, ваш первый код может выполнять нужную мне работу, и поэтому я принял ваш ответ как правильный! Большое спасибо за ваше время всем вам, ребята!
Вы пытаетесь использовать эту информацию в PHP? К сожалению, я не думаю, что у меня достаточно опыта работы с PHP, чтобы помочь (я никогда не использовал массивы PHP). Я даже не знаю, как вы отправляете это на свой сервер... но какой бы формат вы ни использовали, вам придется каким-то образом извлечь и преобразовать его на другом конце, используя функцию, написанную на PHP. Извините, может кто ответит.
Майкл Г. извините, что снова обратил на это ваше внимание, но я обнаружил, что когда я выбираю 2 службы, например, массив, если он заполнен последней выбранной информацией о службе, не все выбраны.. Можно ли это исправить?
@Europeuser, поскольку вы решили использовать «data-trener» в качестве своего ключа, и он одинаков для всех служб (13), они перезаписывают друг друга. (Как и в массиве, только 1 данные могут быть в слоте 13. Добавьте данные в слот 13 снова, и вы перезапишете/сотрете все, что было раньше). Вам нужно будет использовать уникальный ключ, а не «дата-тренер». Глядя на ваш массив PHP, я думаю, вы хотели использовать значение флажка? (Возможно?) Я обновлю код, но если вы не уверены, чего хотите... Возможно, вы этого не получите.
У вас есть var trener_services = ... внутри вашего обработчика событий. Это совершенно не связано с глобальным var trener_services = ..., который вы определяете вне обработчика событий. То есть все, что вы делаете с trener_services внутри вашего обработчика событий, вообще не влияет на глобальную переменную...