johannheyne / acf-table-field-pro-support

0 stars 0 forks source link

Use Table inside ACF Repeater #3

Open zzTAz opened 2 weeks ago

zzTAz commented 2 weeks ago

Hi there,

I’ve been using your plugin for a few days now and I’m very pleased with it. I’m facing an issue with displaying tables inside a repeater. Displaying a single table was easy by following your guide "How to use the table field in Elementor Page Builder?" and adapting it for Bricks Builder. However, I’m struggling to display a table within a repeater. Other repeater fields display without issues.

I would appreciate any help you can provide. Thanks and keep up the good work.

johannheyne commented 2 weeks ago

If you are using the free version, you could use the more advances shortcode setup.

function shortcode_acf_tablefield( $atts ) {

    $a = shortcode_atts( array(
        'table-class' => '',
        'field-name' => false, // use a slash "/" to separate group field name and table subfield name
        'post-id' => false,
    ), $atts );

    // Return if no field name is given
    if ( ! is_string( $a['field-name'] ) ) {

        return '';
    }

    // May gets sub fields names
    $field_names = explode( '/', $a['field-name'] );

    // Gets the root fields value
    $table = get_field( $field_names[0], $a['post-id'] );

    // May gets a table subfields value
    foreach ( $field_names as $key => $name ) {

        if ( 0 < $key ) {

            $table = $table[ $name ];
        }
    }

    $return = '';

    if ( $table ) {

        $return .= '<table class="' . $a['table-class'] . '" border="0">';

            if ( ! empty( $table['caption'] ) ) {

                echo '<caption>' . $table['caption'] . '</caption>';
            }

            if ( $table['header'] ) {

                $return .= '<thead>';

                    $return .= '<tr>';

                        foreach ( $table['header'] as $th ) {

                            $return .= '<th>';
                                $return .= $th['c'];
                            $return .= '</th>';
                        }

                    $return .= '</tr>';

                $return .= '</thead>';
            }

            $return .= '<tbody>';

                foreach ( $table['body'] as $tr ) {

                    $return .= '<tr>';

                        foreach ( $tr as $td ) {

                            $return .= '<td>';
                                $return .= $td['c'];
                            $return .= '</td>';
                        }

                    $return .= '</tr>';
                }

            $return .= '</tbody>';

        $return .= '</table>';
    }

    return $return;
}

add_shortcode( 'tablefield', 'shortcode_acf_tablefield' );

Then give the repeater field name and the table field name in the shortcode separated by a slash: [tablefield field-name="repeater-field-name/table-subfield-name"]

If you are using the pro version, the shortcode setup would be a little easier:

function shortcode_acf_tablefield_pro( $atts ) {

    $a = shortcode_atts( array(
        'table-class' => '',
        'field-name' => false, // use a slash "/" to separate group field name and table subfield name
        'post-id' => false,
    ), $atts );

    // Return if no field name is given
    if ( ! is_string( $a['field-name'] ) ) {

        return '';
    }

    // May gets sub fields names
    $field_names = explode( '/', $a['field-name'] );

    // Gets the root fields value
    $table = get_field( $field_names[0], $a['post-id'] );

    // May gets a table subfields value
    foreach ( $field_names as $key => $name ) {

        if ( 0 < $key ) {

            $table = $table[ $name ];
        }
    }

    $return = '';

    if ( $table ) {

        $return = get_table( $table );
    }

    return $return;
}

add_shortcode( 'tablefield_pro', 'shortcode_acf_tablefield_pro' );

[tablefield_pro field-name="repeater-field-name/table-subfield-name"]

Does that help?

zzTAz commented 2 weeks ago

Thank you so much for your prompt response. Unfortunately, I am still unable to display a table within a repeater using the provided code. I must be missing something, although I am able to display tables outside the repeater or other custom fields inside the repeater without any issues.

I have created a short video that might help in diagnosing the problem. I appreciate your assistance.

Thank you very much! https://drive.google.com/file/d/1Iqn5Ny_gLPg7TR6DukRuMvCxoGtjQS5t/view?usp=drive_link

johannheyne commented 2 weeks ago

Thanks, the video helped a lot.

Since the shortcode is executed in a repeater loop (block with repeater field type), the fields of a repeater item can queried using the ACF methode get_sub_field( 'your_field_name' ) function.

The following code should output the table.

function shortcode_acf_tablefield_subfield( $atts ) {

    $a = shortcode_atts( array(
        'table-class' => '',
        'field-name' => false,
    ), $atts );

    // Return if no field name is given
    if ( ! is_string( $a['field-name'] ) ) {

        return '';
    }

    // Gets field inside a repeater
    $table = get_sub_field( $a['field-name'] );

    $return = '';

    if ( $table ) {

        $return .= '<table class="' . $a['table-class'] . '" border="0">';

            if ( ! empty( $table['caption'] ) ) {

                echo '<caption>' . $table['caption'] . '</caption>';
            }

            if ( $table['header'] ) {

                $return .= '<thead>';

                    $return .= '<tr>';

                        foreach ( $table['header'] as $th ) {

                            $return .= '<th>';
                                $return .= $th['c'];
                            $return .= '</th>';
                        }

                    $return .= '</tr>';

                $return .= '</thead>';
            }

            $return .= '<tbody>';

                foreach ( $table['body'] as $tr ) {

                    $return .= '<tr>';

                        foreach ( $tr as $td ) {

                            $return .= '<td>';
                                $return .= $td['c'];
                            $return .= '</td>';
                        }

                    $return .= '</tr>';
                }

            $return .= '</tbody>';

        $return .= '</table>';
    }

    return $return;
}

add_shortcode( 'tablefield_subfield', 'shortcode_acf_tablefield_subfield' );

If it doesn't work, I'll take another look at it. I wasn't aware of these page builders and need to add more documentation.

Thanks, Johann

zzTAz commented 1 week ago

thanks for your help. Made some adjustments and now it seems to work (outside) the repeater block

` function shortcode_acf_repeater_tablefield( $atts ) {

$a = shortcode_atts( array(
    'table-class' => '',
    'repeater-name' => false,
    'field-name' => false,
    'index' => 1, // Default to 1st table if no index is specified
), $atts );

// Return if no repeater or field name is given
if ( ! is_string( $a['repeater-name'] ) || ! is_string( $a['field-name'] ) ) {
    return '';
}

$repeater_name = $a['repeater-name'];
$field_name = $a['field-name'];
$index = intval($a['index']) - 1; // Convert to zero-based index

// Get the repeater field
$repeater = get_field($repeater_name);

if (!$repeater || !isset($repeater[$index])) {
    return '';
}

$table = $repeater[$index][$field_name];

if (!$table) {
    return '';
}

$return = '<table class="' . esc_attr( $a['table-class'] ) . '" border="0">';

if ( ! empty( $table['caption'] ) ) {
    $return .= '<caption>' . esc_html( $table['caption'] ) . '</caption>';
}

if ( ! empty( $table['header'] ) ) {
    $return .= '<thead><tr>';
    foreach ( $table['header'] as $th ) {
        $return .= '<th>' . esc_html( $th['c'] ) . '</th>';
    }
    $return .= '</tr></thead>';
}

if ( ! empty( $table['body'] ) ) {
    $return .= '<tbody>';
    foreach ( $table['body'] as $tr ) {
        $return .= '<tr>';
        foreach ( $tr as $td ) {
            $return .= '<td>' . esc_html( $td['c'] ) . '</td>';
        }
        $return .= '</tr>';
    }
    $return .= '</tbody>';
}

$return .= '</table>';

return $return;

}

add_shortcode( 'repeater_tablefield', 'shortcode_acf_repeater_tablefield' ); `

Shortcode = [repeater_tablefield repeater-name="YourRepeaterNameHere" field-name="YourTableFieldHere" table-class="yourTableClass" index="1"]

johannheyne commented 1 week ago

Well done. I didn't understand that you wanted to query a specific repeater entry from outside the repeater loop.