Почему некорректно сохраняется мульти checkbox в повторяющихся полях виджета wordpress?
Всем привет!
В wordpress виджете с полями репитерами добавил checkbox, но не могу разобраться с багом сохранения и вывода состояния установлена ли галочка.
К примеру, добавил 4 блока с полями (1 из которых чекбокс):
1 - если во всех блоках включаю все галочки, то они все сохраняются
2 - если снимаю 2 галочки, то при сохранении она исчезает только у последнего элемента, 3 и двоих последних
3 - а, если все галочки снимаю, то при сохранении галочка всегда остаётся у первого
Код виджета
<?php class My_WidgetBase extends WP_Widget { //бэкенд public function form( $instance ) { if ( isset( $instance[ 'blank' ]) ) { $blank = $instance[ 'blank' ]; } ?> <div id="repeatable-fieldset-one"> <?php if (!empty($text)) : foreach ( $text as $k => $x ) { if(!empty($x)) { ?> <div class="block"> <p><input type="text" name="<?php echo $this->get_field_name( 'link' ); ?>[]" value="<?php echo esc_attr( $link[$k] ); ?>"></p> <p><label for="<?php echo $this->get_field_id( 'blank' ).$k; ?>">Открывать в новой вкладке?</label><input class="widefat" id="<?php echo $this->get_field_id( 'blank' ).$k; ?>" name="<?php echo $this->get_field_name( 'blank' ); ?>[]" type="checkbox" value="<?php echo esc_attr($blank[$k]); ?>" <?php checked("1", array_key_exists($k, $blank)); ?> /></p> <a class="button remove-row" href="#">Удалить блок</a> </div> <?php } } else : // начальный пустой блок ?> <div class="block"> <p><input type="text" name="<?php echo $this->get_field_name( 'link' ); ?>[]" value=""></p> <p><label for="<?php echo $this->get_field_id( 'blank' ); ?>">Открывать в новой вкладке?</label><input class="widefat" id="<?php echo $this->get_field_id( 'blank' ); ?>" name="<?php echo $this->get_field_name( 'blank' ); ?>[]" type="checkbox" value="" checked="checked" /></p> </div> <?php endif; ?> </div> <?php } //сохранение public function update( $new_instance, $old_instance ) { $instance['link'] = ( ! empty( $new_instance['link'] ) ) ? $new_instance['link'] : ''; $instance['blank'] = ( ! empty( $new_instance['blank'] ) ) ? 1 : false; return $instance; } } |
<?php class My_WidgetBase extends WP_Widget { //бэкенд public function form( $instance ) { if ( isset( $instance[ 'blank' ]) ) { $blank = $instance[ 'blank' ]; } ?> <div id="repeatable-fieldset-one"> <?php if (!empty($text)) : foreach ( $text as $k => $x ) { if(!empty($x)) { ?> <div class="block"> <p><input type="text" name="<?php echo $this->get_field_name( 'link' ); ?>[]" value="<?php echo esc_attr( $link[$k] ); ?>"></p> <p><label for="<?php echo $this->get_field_id( 'blank' ).$k; ?>">Открывать в новой вкладке?</label><input class="widefat" id="<?php echo $this->get_field_id( 'blank' ).$k; ?>" name="<?php echo $this->get_field_name( 'blank' ); ?>[]" type="checkbox" value="<?php echo esc_attr($blank[$k]); ?>" <?php checked("1", array_key_exists($k, $blank)); ?> /></p> <a class="button remove-row" href="#">Удалить блок</a> </div> <?php } } else : // начальный пустой блок ?> <div class="block"> <p><input type="text" name="<?php echo $this->get_field_name( 'link' ); ?>[]" value=""></p> <p><label for="<?php echo $this->get_field_id( 'blank' ); ?>">Открывать в новой вкладке?</label><input class="widefat" id="<?php echo $this->get_field_id( 'blank' ); ?>" name="<?php echo $this->get_field_name( 'blank' ); ?>[]" type="checkbox" value="" checked="checked" /></p> </div> <?php endif; ?> </div> <?php } //сохранение public function update( $new_instance, $old_instance ) { $instance['link'] = ( ! empty( $new_instance['link'] ) ) ? $new_instance['link'] : ''; $instance['blank'] = ( ! empty( $new_instance['blank'] ) ) ? 1 : false; return $instance; } }
Дополнительно
на выходе пары label for и input id - соответствуют? У каждой пары свое, уникальное?
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Проблема с checkbox в повторяющихся полях виджета обычно возникает из-за того, что unchecked checkbox вообще не отправляется в POST. Если вы сохраняете массив по индексам, то после снятия галочки индексы сдвигаются или старое значение остаётся.
Нужно для каждого checkbox сохранять значение явно: 1 или 0. В форме перед checkbox часто добавляют hidden input с тем же именем и значением 0:
<input type="hidden" name="<?php echo esc_attr($this->get_field_name('items')); ?>[<?php echo $i; ?>][enabled]" value="0"> <input type="checkbox" name="<?php echo esc_attr($this->get_field_name('items')); ?>[<?php echo $i; ?>][enabled]" value="1" <?php checked(! empty($item['enabled'])); ?>>
В методе
update()нормализуйте данные:foreach ($new_instance['items'] as $i => $item) { $instance['items'][$i]['enabled'] = ! empty($item['enabled']) ? 1 : 0; $instance['items'][$i]['title'] = sanitize_text_field($item['title'] ?? ''); }
Главная идея: не полагайтесь на сам факт наличия checkbox в POST. Для снятой галочки браузер ничего не отправляет, поэтому вы должны сами записать 0.
Также следите, чтобы у каждого блока репитера был стабильный индекс. Если при удалении/добавлении блоков индексы ломаются, состояние полей будет путаться.