CMB2 / CMB2-Snippet-Library

CMB2 Code Snippet Library
360 stars 145 forks source link

Update widget snippet with working group fields #66

Open rubengc opened 7 years ago

rubengc commented 7 years ago

I am trying to make group fields work at widgets area

First I added a new loop to add group fields correctly:

        public function cmb2( $saving = false ) {

            // Create a new box in the class
            $cmb2 = new CMB2( array(
                'id'      => $this->option_name .'_box', // Option name is taken from the WP_Widget class.
                'hookup'  => false,
                'show_on' => array(
                    'key'   => 'options-page', // Tells CMB2 to handle this as an option
                    'value' => array( $this->option_name )
                ),
            ), $this->option_name );

            foreach ( $this->fields as $field ) {
                if ( ! $saving ) {
                    $field['id'] = $this->get_field_name( $field['id'] );
                }

                $field['default_cb'] = array( $this, 'default_cb' );

                $field_id = $cmb2->add_field( $field );

                // Support for group fields
                if( $field['type'] == 'group' ) {
                    foreach( $field['fields'] as $group_field ) {
                        $cmb2->add_group_field( $field_id, $group_field );
                    }
                }
            }

            return $cmb2;
        }

And the js event to make repeatables working:

(function( window, document, $, cmb ) {
    $( document ).on('widget-updated widget-added', function( event, widget ) {
        var $metabox = $(widget).find('.cmb2-wrap > .cmb2-metabox');

        $metabox
            .on('click', '.cmb-add-group-row', cmb.addGroupRow)
            .on('click', '.cmb-add-row-button', cmb.addAjaxRow)
            .on('click', '.cmb-remove-group-row', cmb.removeGroupRow)
            .on('click', '.cmb-remove-row-button', cmb.removeAjaxRow);
    });
})( window, document, jQuery, window.CMB2 );

But I miss something, because i got a duplicated group fields in each group, and also save functionallity is not working

Can someone help me to get it working?

Thanks in advance!

rubengc commented 7 years ago

After investigate it, I do not need add any extra check for group fields at widget class

The value is stored correctly, but for some reason is not loaded correctly

rubengc commented 7 years ago

is possible that default_cb is not called on repeatable groups because it returns false instead of null?

rubengc commented 7 years ago

I try to override how CMB2 is getting group values because is trying to retrieve a wrong options index

I dumped the contents of $args in cmb2_override_meta_value and It has type => post instead of options-page (and metabox has correctly configured show_on argument)

I need to investigate It a bit more

rubengc commented 7 years ago

I got some progress about this

I am able to get group field elements values, but for some reason it only return the first element

        public function cmb2( $saving = false ) {

            // Create a new box in the class
            $cmb2 = new CMB2( array(
                'id'      => $this->option_name .'_box', // Option name is taken from the WP_Widget class.
                'hookup'  => false,
                'show_on' => array(
                    'key'   => 'options-page', // Tells CMB2 to handle this as an option
                    'value' => array( $this->option_name )
                ),
            ), $this->option_name );

            foreach ( $this->fields as $field ) {
                if ( ! $saving ) {
                    $field['id'] = $this->get_field_name( $field['id'] );
                }

                if( $field['type'] == 'group' ) {
                    // Update group fields default_cb
                    foreach( $field['fields'] as $group_field_index => $group_field ) {
                        $group_field['default_cb'] = array( $this, 'default_cb' );

                        $field['fields'][$group_field_index] = $group_field;
                    }
                }

                $field['default_cb'] = array( $this, 'default_cb' );

                $cmb2->add_field( $field );
            }

            return $cmb2;
        }
        public function default_cb( $field_args, $field ) {
            if( $field->group ) {
                if( isset( $this->_instance[ $field->group->args( 'id_key' ) ] ) ) {
                    $data = $this->_instance[ $field->group->args( 'id_key' ) ];

                    return is_array( $data ) && isset( $data[ $field->group->index ][ $field->args( 'id_key' ) ] )
                        ? $data[ $field->group->index ][ $field->args( 'id_key' ) ]
                        : null;
                } else {
                    return null;
                }
            }

            return isset( $this->_instance[ $field->args( 'id_key' ) ] )
                ? $this->_instance[ $field->args( 'id_key' ) ]
                : null;
        }
rubengc commented 7 years ago

Finally I got it working, I need to add a filter to cmb2_override_meta_value to retrieve correctly group field value

jazzsequence commented 7 years ago

@rubengc would you be willing to submit a PR on the widget snippet so we can see what worked and potentially add that code to the snippet library?

rubengc commented 7 years ago

The problem (that i hackily solved) is CMB2 do not call default_cb on group field but default_cb is called in fields inside a group

If CMB2 adds this check to group fields probably my solution will not be needle

jazzsequence commented 7 years ago

👍 This is really an issue in CMB2, then, rather than the snippet library, but I will leave it open here for context.

av-nexter commented 6 years ago
public function form( $instance ) {
        add_filter( 'cmb2_override_meta_value', array( $this, 'cmb2_override_meta_value' ), 11, 4 );

        // If there are no settings, set up defaults
        $this->_instance = wp_parse_args( (array) $instance, self::$defaults );

        $cmb2 = $this->cmb2();

        $cmb2->object_id( $this->option_name );
        CMB2_hookup::enqueue_cmb_css();
        CMB2_hookup::enqueue_cmb_js();
        $cmb2->show_form();

        remove_filter( 'cmb2_override_meta_value', array( $this, 'cmb2_override_meta_value' ) );
    }

public function cmb2_override_meta_value( $value, $object_id, $args, $field ) {
        if ( $field->group || 'group' === $field->type() ) {
            if ( isset( $field->args['id_key'] ) ) {
                $id_key = $field->args['id_key'];

                if ( isset( $this->_instance[$id_key] ) ) {
                    $value = $this->_instance[$id_key];
                }
            }
        }

        return $value;
    }
 public function cmb2( $saving = false ) {

            // Create a new box in the class
            $cmb2 = new CMB2( array(
                'id'      => $this->option_name .'_box', // Option name is taken from the WP_Widget class.
                'hookup'  => false,
                'show_on' => array(
                    'key'   => 'options-page', // Tells CMB2 to handle this as an option
                    'value' => array( $this->option_name )
                ),
            ), $this->option_name );

            foreach ( $this->fields as $field ) {
                if ( ! $saving ) {
                    $field['id'] = $this->get_field_name( $field['id'] );
                }

                if( $field['type'] == 'group' ) {
                    // Update group fields default_cb
                    foreach( $field['fields'] as $group_field_index => $group_field ) {
                        $group_field['default_cb'] = array( $this, 'default_cb' );

                        $field['fields'][$group_field_index] = $group_field;
                    }
                }

                $field['default_cb'] = array( $this, 'default_cb' );

                $cmb2->add_field( $field );
            }

            return $cmb2;
        }

 public function default_cb( $field_args, $field ) {
            if( $field->group ) {
                if( isset( $this->_instance[ $field->group->args( 'id_key' ) ] ) ) {
                    $data = $this->_instance[ $field->group->args( 'id_key' ) ];

                    return is_array( $data ) && isset( $data[ $field->group->index ][ $field->args( 'id_key' ) ] )
                        ? $data[ $field->group->index ][ $field->args( 'id_key' ) ]
                        : null;
                } else {
                    return null;
                }
            }

            return isset( $this->_instance[ $field->args( 'id_key' ) ] )
                ? $this->_instance[ $field->args( 'id_key' ) ]
                : null;
        }

(function( window, document, $ ) {
    $( document ).on('widget-updated widget-added', function( event, widget ) {
        var $metabox = $(widget).find('.cmb2-wrap > .cmb2-metabox'),
            cmb = window.CMB2;

        $metabox
            .on('click', '.cmb-add-group-row', cmb.addGroupRow)
            .on('click', '.cmb-add-row-button', cmb.addAjaxRow)
            .on('click', '.cmb-remove-group-row', cmb.removeGroupRow)
            .on('click', '.cmb-remove-row-button', cmb.removeAjaxRow)
            .on( 'click', '.cmbhandle, .cmbhandle + .cmbhandle-title', cmb.toggleHandle );

    });
})( window, document, jQuery );
rubengc commented 5 years ago

Note: ColorPicker fields gets destroyed after field save on widgets area a way to fix it:

// Auto Call plugin is class is color-picker
jQuery( document ).ready( function( $ ) {
    $( '.color-picker' ).wpColorPicker();

     // Initialize on widgets area
    $(document).on('widget-updated widget-added', function(e, widget) {
        widget.find( '.color-picker, .cmb2-colorpicker' ).wpColorPicker();
    });
} );

An explanation on this can be found here