Cómo agregar un selector de fechas en campos personalizados dinámicos (Repeater Fields)

6 jul 2017, 17:42:35
Vistas: 15.2K
Votos: 0

He creado Campos Personalizados Dinámicos (Repeater Fields) en mis tipos de posts personalizados. Funciona perfectamente. Quiero agregar un nuevo campo de Selector de Fechas JQuery. Intenté crear el código y también busqué en la web pero no tuve éxito.

Por favor ayúdenme.

A continuación está mi código.

function project_rewards_select_options() {
    $options = array (
        'Opción 1' => 'Opción 1',
        'Opción 2' => 'Opción 2',
        'Opción 3' => 'Opción 3',
    );

    return $options;
}

function project_reward_callback( $post ) {
    wp_nonce_field( 'project_reward_nonce', 'project_reward_nonce' );
    $reward_value = get_post_meta( get_the_ID(), '_project_rewards', true );
    $options = project_rewards_select_options();

?>

    <script type="text/javascript">
    jQuery(document).ready(function( $ ){
        $( '#add-row' ).on('click', function() {
            var row = $( '.empty-row.screen-reader-text' ).clone(true);
            row.removeClass( 'empty-row screen-reader-text' );
            row.insertBefore( '#repeatable-fieldset-one tbody>tr:last' );
            return false;
        });

        $( '.remove-row' ).on('click', function() {
            $(this).parents('tr').remove();
            return false;
        });
    });
    </script>

    <table id="repeatable-fieldset-one" width="100%">

    <thead>
        <tr>
            <th width="15%">Cantidad de Recompensa</th>
            <th width="25%">Título de Recompensa</th>
            <th width="10%">Envío</th>       
            <th width="45%">Descripción de Recompensa</th>
            <th width="5%"></th>                    
        </tr>
    </thead>

    <tbody>

<?php

    ( $reward_value );

    foreach ( $reward_value as $field ) {

?>

    <tr>
        <td><input type="text" class="widefat" name="reward[]" value="<?php if ( isset ( $field['reward'] ) ) echo esc_attr( $field['reward'] ); ?>" pattern="[1-9]\d*" /></td>

        <td><input type="text" class="widefat" name="reward_title[]" value="<?php if ( isset ( $field['reward_title'] ) ) echo esc_attr( $field['reward_title'] ); ?>" /></td>

        <td>
            <select class="widefat" name="reward_shipping[]">
            <?php foreach ( $options as $label => $value ) : ?>
            <option value="<?php echo $value; ?>"<?php selected( $field['reward_shipping'], $value ); ?>><?php echo $label; ?></option>
            <?php endforeach; ?>
            </select>
        </td>

        <td><textarea class="widefat" name="reward_description[]"><?php if ( isset ( $field['reward_description'] ) ) echo esc_attr( $field['reward_description'] ); ?></textarea></td>

        <td><input type="image" class="remove-row" src="<?php bloginfo('template_directory'); ?>/assets/images/remove-icon.png" alt="Eliminar"  width="35" height="35"></td>
    </tr>

<?php } ?>

    <!-- fila vacía oculta para jQuery -->
    <tr class="empty-row screen-reader-text">
        <td><input type="text" class="widefat" name="reward[]" /></td>

        <td><input type="text" class="widefat" name="reward_title[]" /></td>

        <td>
            <select class="widefat" name="reward_shipping[]">
            <?php foreach ( $options as $label => $value ) : ?>
            <option value="<?php echo $value; ?>"><?php echo $label; ?></option>
            <?php endforeach; ?>
            </select>
        </td>   

        <td><textarea class="widefat" name="reward_description[]" ></textarea></td>

        <td><input type="image" class="remove-row" src="<?php bloginfo('template_directory'); ?>/assets/images/remove-icon.png" alt="Eliminar"  width="35" height="35"></td>
    </tr>

    </tbody>

    </table>

    <p><a id="add-row" class="button" href="#">Agregar Recompensa</a></p>

<?php   

}

function save_project_reward( $post_id ) {

    // Verificar si nuestro nonce está configurado
    if ( ! isset( $_POST['project_reward_nonce'] ) {
        return;
    }

    // Verificar que el nonce es válido
    if ( ! wp_verify_nonce( $_POST['project_reward_nonce'], 'project_reward_nonce' ) ) {
        return;
    }

    // Si es un autoguardado, nuestro formulario no se ha enviado, así que no hacemos nada
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return;
    }

    // Verificar permisos del usuario
    if ( isset( $_POST['post_type'] ) && 'page' == $_POST['post_type'] ) {

        if ( ! current_user_can( 'edit_page', $post_id ) ) {
            return;
        }

    }
    else {

        if ( ! current_user_can( 'edit_post', $post_id ) ) {
            return;
        }
    }

    $reward_data = array();
    $options = project_rewards_select_options();

    $rewards = $_POST['reward'];
    $reward_titles = $_POST['reward_title'];
    $reward_shippings = $_POST['reward_shipping'];
    $reward_descriptions = $_POST['reward_description'];

    $count = count( $rewards );
    for ( $i = 0; $i < $count; $i++ ) {

        if ( $rewards[$i] != '' ) :
            $reward_data[$i]['reward'] = stripslashes( strip_tags( $rewards[$i] ) );

        if ( in_array( $reward_shippings[$i], $options ) )
            $reward_data[$i]['reward_shipping'] = stripslashes( strip_tags( $reward_shippings[$i] ) );
                else
            $reward_data[$i]['reward_shipping'] = '';
endif;

        if ( $reward_titles[$i] != '' ) :
            $reward_data[$i]['reward_title'] = stripslashes( strip_tags( $reward_titles[$i] ) );
endif;

        if ( $reward_descriptions[$i] != '' ) :
            $reward_data[$i]['reward_description'] = stripslashes( $reward_descriptions[$i] );
endif;              

    }

    update_post_meta( $post_id, '_project_rewards', $reward_data );

}

add_action( 'save_post', 'save_project_reward' ); 
3
Comentarios

¿Por qué intentas agregar tu propio JQuery Date Picker si ACF ya tiene este campo?

Cesar Henrique Damascena Cesar Henrique Damascena
6 jul 2017 17:47:13

No quiero usar ACF

Minu Minu
6 jul 2017 18:05:36

Oh, lo siento, error mío, entendí que lo estabas usando

Cesar Henrique Damascena Cesar Henrique Damascena
6 jul 2017 18:23:42
Todas las respuestas a la pregunta 2
0

WordPress ya incluye el datepicker de jQuery. Así que puedes encolar el script predeterminado de WP. Sin embargo, hasta donde sé, ¡WP no incluye los estilos necesarios para el datepicker!
Prueba a encolar el script de WP y, por ejemplo, los estilos de una fuente externa:

function my_datepicker_enqueue() {
            wp_enqueue_script( 'jquery-ui-datepicker' ); // encolar datepicker de WP
            wp_enqueue_style( 'jquery-ui-style', '//ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/base/jquery-ui.css', true);
}
add_action( 'admin_enqueue_scripts', 'my_datepicker_enqueue' );

Crea un nuevo campo de entrada HTML con al menos una clase y un nombre. HTML del campo de entrada: (ya tienes algunos campos definidos, así que ve directo al script)

<input type="text" name="_custom_datepicker[]" id="_custom_datepicker[]" class="my-custom-datepicker-field" value="<?php echo $your_saved_value; ?>" />

Luego añade un script para inicializar el datepicker en nuestro nuevo elemento. Script: (asegúrate de seleccionar el elemento de entrada correcto, aquí buscamos la clase definida porque queremos usar múltiples instancias).

jQuery(document).ready(function($){
    $('.my-custom-datepicker-field').datepicker({
        dateFormat: 'dd-mm-yy', //quizá quieras algo así
        showButtonPanel: true
    });
});

Actualización:
Al principio tuve problemas al leer tu código, y además tienes varios errores. Al principio podía ver el mismo comportamiento extraño. Ahora he configurado un plugin de prueba en un sitio de desarrollo, y ahí ya funciona.

1: Configuraste tu función de guardado de modo que no puedes simplemente introducir una fecha y guardar. Tendrás que añadir también una cantidad, título o descripción para poder guardar. ¿Supongo que esto es intencionado por tu parte?

2: En la función de guardado tienes el siguiente código:

if ( $reward_descriptions[$i] != '' ) :
    $reward_data[$i]['reward_date'] = stripslashes( $reward_dates[$i] );
endif;

¡¿Así que solo cuando el campo de descripción no esté vacío se guardará la fecha?! Parece que esto fue un error tipográfico porque los otros campos están bien. Cambia a:

if ( $reward_data[$i] != '' ) :
    $reward_data[$i]['reward_date'] = stripslashes( $reward_dates[$i] );
endif;

3: En tu código de callback tienes estos campos como datepickers:

<td><input type="text" name="_custom_datepicker[]" id="_custom_datepicker[]" class="my-custom-datepicker-field" value="<?php echo esc_attr( $field['reward_date'] ); ?>" /></td>

y

<td><input type="text" class="my-custom-datepicker-field" name="_custom_datepicker[]" /></td>

Ambos nombrados _custom_datepicker[]. Pero en tu función de guardado intentas guardar campos llamados reward_date en su lugar.

Además, el id debe ser único. Pero añades el mismo id a todos los campos de fecha. Simplemente podrías eliminar el id de estos campos, no es necesario de todos modos.

4. Si añades campos dinámicamente como quieres, necesitas cambiar la función JS del datepicker. Y en lugar de cargar el código JS en línea (y múltiples veces como hiciste), recomiendo encolar un archivo JS. Así que intenta reemplazar tu código JS con algo como esto:

jQuery(document).ready(function($){

    // tu código por defecto
    $( '#add-row' ).on('click', function() {
        var row = $( '.empty-row.screen-reader-text' ).clone(true);
        row.removeClass( 'empty-row screen-reader-text' );
        row.insertBefore( '#repeatable-fieldset-one tbody>tr:last' );
        return false;
    });

    $( '.remove-row' ).on('click', function() {
        $(this).parents('tr').remove();
        return false;
    });

    //cambiado para usarse en campo dinámico que se añade y elimina del DOM
    //si el elemento con la clase .my-custom-datepicker-field recibe foco, añade datepicker
    $(document).on('focus', '.my-custom-datepicker-field', function(){
        $(this).datepicker({
            dateFormat: 'dd-mm-yy', //quizá quieras algo así
            showButtonPanel: true
        });
    });

});

Después de corregir estas cosas y encolar el archivo JS con el código como WordPress lo quiere, ahora funciona.

7 jul 2017 15:07:07
1
-1

@LWS-Mo, Gracias por tu ayuda. He añadido los códigos según correspondía pero el selector de fechas (datepicker) está funcionando de manera extraña. La fecha seleccionada en el primer campo se refleja en los campos subsiguientes. No está funcionando correctamente.

Por favor indícame dónde me estoy equivocando. A continuación está el código.

function project_rewards_select_options() {
    $options = array (
        'Opción 1' => 'Opción 1',
        'Opción 2' => 'Opción 2',
        'Opción 3' => 'Opción 3',
    );

    return $options;
}

function crazicle_project_reward_callback( $post ) {
    wp_nonce_field( 'project_reward_nonce', 'project_reward_nonce' );
    $reward_value = get_post_meta( get_the_ID(), '_project_rewards', true );
    $options = project_rewards_select_options();

?>

    <script type="text/javascript">
    jQuery(document).ready(function( $ ){
        $( '#add-row' ).on('click', function() {
            var row = $( '.empty-row.screen-reader-text' ).clone(true);
            row.removeClass( 'empty-row screen-reader-text' );
            row.insertBefore( '#repeatable-fieldset-one tbody>tr:last' );
            return false;
        });

        $( '.remove-row' ).on('click', function() {
            $(this).parents('tr').remove();
            return false;
        });
    });
    </script>

    <table id="repeatable-fieldset-one" width="100%">

    <thead>
        <tr>
            <th width="15%">Cantidad de recompensa</th>
            <th width="25%">Título de recompensa</th>
            <th width="10%">Envío</th>
            <th width="20%">Fecha</th>                  
            <th width="25%">Descripción de recompensa</th>
            <th width="5%"></th>                    
        </tr>
    </thead>

    <tbody>

<?php

    ( $reward_value );

    foreach ( $reward_value as $field ) {

?>

    <tr>
        <td><input type="text" class="widefat" name="reward[]" value="<?php if ( isset ( $field['reward'] ) ) echo esc_attr( $field['reward'] ); ?>" pattern="[1-9]\d*" /></td>

        <td><input type="text" class="widefat" name="reward_title[]" value="<?php if ( isset ( $field['reward_title'] ) ) echo esc_attr( $field['reward_title'] ); ?>" /></td>

        <td>
            <select class="widefat" name="reward_shipping[]">
            <?php foreach ( $options as $label => $value ) : ?>
            <option value="<?php echo $value; ?>"<?php selected( $field['reward_shipping'], $value ); ?>><?php echo $label; ?></option>
            <?php endforeach; ?>
            </select>
        </td>

        <script type="text/javascript">
            jQuery(document).ready(function($){
    $('.my-custom-datepicker-field').datepicker({
        dateFormat: 'dd-mm-yy', //quizás quieras algo así
        showButtonPanel: true
    });
});
        </script>

        <td><input type="text" name="_custom_datepicker[]" id="_custom_datepicker[]" class="my-custom-datepicker-field" value="<?php echo esc_attr( $field['reward_date'] ); ?>" /></td>

        <td><textarea class="widefat" name="reward_description[]"><?php if ( isset ( $field['reward_description'] ) ) echo esc_attr( $field['reward_description'] ); ?></textarea></td>

        <td><input type="image" class="remove-row" src="<?php bloginfo('template_directory'); ?>/assets/images/remove-icon.png" alt="Eliminar"  width="35" height="35"></td>
    </tr>

<?php } ?>

    <!-- fila vacía oculta para jQuery -->
    <tr class="empty-row screen-reader-text">
        <td><input type="text" class="widefat" name="reward[]" /></td>

        <td><input type="text" class="widefat" name="reward_title[]" /></td>

        <td>
            <select class="widefat" name="reward_shipping[]">
            <?php foreach ( $options as $label => $value ) : ?>
            <option value="<?php echo $value; ?>"><?php echo $label; ?></option>
            <?php endforeach; ?>
            </select>
        </td>

        <script type="text/javascript">
            jQuery(document).ready(function($){
    $('.my-custom-datepicker-field').datepicker({
        dateFormat: 'dd-mm-yy', //quizás quieras algo así
        showButtonPanel: true
    });
});
        </script>        

        <td><input type="text" class="my-custom-datepicker-field" name="_custom_datepicker[]" /></td>          

        <td><textarea class="widefat" name="reward_description[]" ></textarea></td>

        <td><input type="image" class="remove-row" src="<?php bloginfo('template_directory'); ?>/assets/images/remove-icon.png" alt="Eliminar"  width="35" height="35"></td>
    </tr>

    </tbody>

    </table>

    <p><a id="add-row" class="button" href="#">Añadir recompensa</a></p>

<?php   

}

function save_project_reward( $post_id ) {

    // Verificar si nuestro nonce está establecido
    if ( ! isset( $_POST['project_reward_nonce'] ) ) {
        return;
    }

    // Verificar que el nonce es válido
    if ( ! wp_verify_nonce( $_POST['project_reward_nonce'], 'project_reward_nonce' ) ) {
        return;
    }

    // Si es un autoguardado, nuestro formulario no ha sido enviado, así que no hacemos nada
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return;
    }

    // Verificar permisos del usuario
    if ( isset( $_POST['post_type'] ) && 'page' == $_POST['post_type'] ) {

        if ( ! current_user_can( 'edit_page', $post_id ) ) {
            return;
        }

    }
    else {

        if ( ! current_user_can( 'edit_post', $post_id ) ) {
            return;
        }
    }

    $reward_data = array();
    $options = project_rewards_select_options();

    $rewards = $_POST['reward'];
    $reward_titles = $_POST['reward_title'];
    $reward_shippings = $_POST['reward_shipping'];
    $reward_dates = $_POST['reward_date'];    
    $reward_descriptions = $_POST['reward_description'];

    $count = count( $rewards );
    for ( $i = 0; $i < $count; $i++ ) {

        if ( $rewards[$i] != '' ) :
            $reward_data[$i]['reward'] = stripslashes( strip_tags( $rewards[$i] ) );

        if ( in_array( $reward_shippings[$i], $options ) )
            $reward_data[$i]['reward_shipping'] = stripslashes( strip_tags( $reward_shippings[$i] ) );
                else
            $reward_data[$i]['reward_shipping'] = '';
endif;

        if ( $reward_titles[$i] != '' ) :
            $reward_data[$i]['reward_title'] = stripslashes( strip_tags( $reward_titles[$i] ) );
endif;

        if ( $reward_descriptions[$i] != '' ) :
            $reward_data[$i]['reward_description'] = stripslashes( $reward_descriptions[$i] );
endif;

        if ( $reward_descriptions[$i] != '' ) :
            $reward_data[$i]['reward_date'] = stripslashes( $reward_dates[$i] );
endif;            

    }

    update_post_meta( $post_id, '_project_rewards', $reward_data );

}

add_action( 'save_post', 'save_project_reward' );
7 jul 2017 16:12:22
Comentarios

Lo siento, no recibí ninguna notificación, acabo de ver que intentaste contactarme. Actualizaré mi respuesta lo antes posible.

LWS-Mo LWS-Mo
13 oct 2017 17:19:01