Chaque champ de la validation de formulaire Woocommerce par défaut a cette balise:
<p class="form-row form-row-first validate-required" id="billing_first_name_field" data-priority="10">
<label for="billing_first_name" class="">Name
<abbr class="required" title="required">*</abbr>
</label>
<span class="woocommerce-input-wrapper">
<input type="text" class="input-text " name="billing_first_name" id="billing_first_name" placeholder="" value="" autocomplete="given-name">
</span>
</p>
Maintenant je veux:
<div class="single-field-wrapper"><p [...] </div>
<div class="first-and-second-field-wrapper"> [...] </div>
Pour ce faire, j'ai essayé d'utiliser les crochets de filtre mis à disposition par function woocommerce_form_field( $key, $args, $value = null )
appelé dans le modèle form-billing.php
de cette manière:
<?php
$fields = $checkout->get_checkout_fields( 'billing' );
foreach ( $fields as $key => $field ) {
if ( isset( $field['country_field'], $fields[ $field['country_field'] ] ) ) {
$field['country'] = $checkout->get_value( $field['country_field'] );
}
woocommerce_form_field( $key, $field, $checkout->get_value( $key ) );
}
?>
Donc, dans functions.php
j'ai écrit:
function change_woocommerce_field_markup($field, $key, $args, $value){
$field = '<div class="single-field-wrapper">'.$field.'</div>';
if($key === 'billing_first_name') {
$field = '<div class="first-and-second-field-wrapper">'.$field;
}
else if ($key === 'billing_last_name') {
$field = $field.'</div>';
}
else {
$field = $field;
}
return $field;
}
add_filter("woocommerce_form_field","change_woocommerce_field_markup", 10, 4);
De façon inattendue, je reçois ce balisage:
<div class="first-and-second-field-wrapper">
<div class="single-field-wrapper">
<div class="single-field-wrapper">
[here there are all the fields, one under the other ]
</div>
<div class="single-field-wrapper"></div>
<div class="single-field-wrapper"></div>
<div class="single-field-wrapper"></div>
<div class="single-field-wrapper"></div>
<div class="single-field-wrapper"></div>
<div class="single-field-wrapper"></div>
<div class="single-field-wrapper"></div>
<div class="single-field-wrapper"></div>
</div>
Tout le monde peut expliquer pourquoi ce comportement inattendu?
Il n'y a pas de hook woocommerce_form_field
, il y a de hook woocommerce_form_field_{$args[type]}
(doc) .
$args[type]
peut être (regardez ici pour les options disponibles):
Le code ci-dessous va envelopper les champs 'billing_first_name' et 'billing_last_name' dans un wrapper comme <div class="first-and-second-field-wrapper"> [...] </div>
.
function change_woocommerce_field_markup($field, $key, $args, $value) {
$field = '<div class="single-field-wrapper">'.$field.'</div>';
if($key === 'billing_first_name')
$field = '<div class="first-and-second-field-wrapper">'.$field;
else if ($key === 'billing_last_name')
$field = $field.'</div>';
return $field;
}
add_filter("woocommerce_form_field_text","change_woocommerce_field_markup", 10, 4);
Il encapsulera également les champs de type text
avec <div class="single-field-wrapper">...</div>
.
MAIS
Certains champs de texte ayant leur propre type (comme state ou email) nécessitent des points d'ancrage supplémentaires, par exemple:
add_filter("woocommerce_form_field_country","change_woocommerce_field_markup", 10, 4);
add_filter("woocommerce_form_field_email","change_woocommerce_field_markup", 10, 4);
UPDATE # 1
Le code ci-dessus fonctionne dans WC-v3.3.7.
Dans WC-v3.4.xx, vous obtenez ceci:
<div class="first-and-second-field-wrapper">
<div class="single-field-wrapper">
<div class="single-field-wrapper">
[here there are all the fields, one under the other ]
</div>
<div class="single-field-wrapper"></div>
<div class="single-field-wrapper"></div>
<div class="single-field-wrapper"></div>
....
<div class="single-field-wrapper"></div>
</div>
parce que javascript trie les lignes de formulaire dans .woocommerce-billing-fields__field-wrapper
. Regardez le fichier woocommerce/assets/js/frontend/address-i18n.js
, à partir de la ligne 99.
JS trouve toutes les balises HTML avec la classe ".form-row" dans le wrapper, prend le parent de first item (balise avec la classe .form-row
), trie les éléments par priorité et les insère dans élément parent précédemment sélectionné .
Pour le test, modification dans le fichier address-i18.js
, à la ligne 99var fieldsets = $('.woocommerce-billing-fields__field-wrapper, ...
àvar fieldsets = $('.woocommerce-billing-fields__field-wrapper2, ...
et téléchargez au format address-i18.min.js
.
Supprimer le tri JS n'est pas une solution, c'est juste un test. Sans le tri par JS, vous obtiendrez ceci:
<div class="first-and-second-field-wrapper">
<div class="single-field-wrapper">
<p class="form-row ..." id="billing_first_name_field"> <label for="billing_first_name"> ... </p>
</div>
<div class="single-field-wrapper">
<p class="form-row ..." id="billing_last_name_field"> <label for="billing_last_name">... </p>
</div>
</div>
<div class="single-field-wrapper">
<p class="form-row ..." id="billing_company_field"> <label for="billing_company">... </p>
</div>