Custom Fields
Re-Envisioned
Support General Option Group support for Select/Select Advanced Field Types

This topic contains 8 replies, has 2 voices, and was last updated by  pluginoven 1 year, 2 months ago.

  • Creator
    Topic
  • #8932
    Resolved
    pluginoven
    Participant

    There is currently no support for the <a> tag in the Select and Select-Advanced field types. Before I start creating a custom field type that supports optgroup, I thought it best to get some thoughts on this.

    Logically, the field options could be defined like so:

    'options'    => array(
                            'Monkeys' => array(
                                'king_kong' => 'King Kong',
                                'curious_george' => 'Curious George'
                            ),
                            'Donkeys' => array(
                                'eeyore' => 'Eeyore',
                                'gus' => 'Gus'
                            )
                    ),

    From a quick investigation the following elements would need to be overwritten

    1. RWMB_Choice_Field > get_options
    2. RWMB_Select_Field > walk
    3. RWMB_Walker_Select > start_el

    Does it make more sense to change the core to support this standard HTML element, or build a custom field type? Am I the only one that missed the optgroup tag? Thoughts?

Viewing 8 replies - 1 through 8 (of 8 total)
  • Author
    Replies
  • #8933

    pluginoven
    Participant

    Looks like I missed the closing a tag on the link to optgroup. Sorry, wish I could edit, but that’s not possible.

    #8947

    pluginoven
    Participant

    Thank you for fixing the link in the initial post. Should read:
    There is currently no support for the <optgroup> tag in the Select and Select-Advanced field types…

    #8948

    pluginoven
    Participant

    Update: there seems to be a special field type (not in the documentation, by the way) called a ‘select-tree’ that was brought up in this thread: https://metabox.io/support/topic/custom-select-tree/

    Seems like a better starting point then the standard select field….

    #8960

    Anh Tran
    Keymaster

    Hello,

    Thanks for bringing an interesting question. I was thinking about this, too. However, the problem is changing the syntax, which requires a lot of code to be modified. Not sure how to do it best and clean.

    #8964

    pluginoven
    Participant

    I was able to achieve something building off of the standard select field. I created a new field type called: ‘selectomatic’ which is defined as so:

    array(
        'type'    => 'selectomatic',
        'id'      => 'animal_select',
        'name'    => 'Animals',
        'options' => array(
            array( 'value' => 'monkey', 'label' => 'Monkeys' ),
                array( 'value' => 'king_kong', 'label' => 'King Kong', 'parent' => 'monkey' ),
                array( 'value' => 'curious_george', 'label' => 'Curious George', 'parent' => 'monkey' ),
            array( 'value' => 'donkey', 'label' => 'Donkeys' ),
                array( 'value' => 'eeyore', 'label' => 'Eeyore', 'parent' => 'donkey' ),
                array( 'value' => 'guss', 'label' => 'Gus', 'parent' => 'donkey' ),
        ),
        'flatten' => false
    ),

    Then I extended the Select Field Class and Select Walker Class like so:

    class RWMB_Walker_Selectomatic extends RWMB_Walker_Select {
    
    		public function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {
    			$label  = $this->db_fields['label'];
    			$id     = $this->db_fields['id'];
    			$meta   = $this->meta;
    			
    			if($depth){
    				$output .= sprintf(
    					'<option value="%s" %s>%s</option>',
    					esc_attr( $object->$id ),
    					selected( in_array( $object->$id, $meta ), true, false ),
    					esc_html( RWMB_Field::filter( 'choice_label', $object->$label, $this->field, $object )
    					)
    				);
    			}
    			else{
    				$output .= sprintf(
    					'<optgroup label="%s">',
    					esc_html( RWMB_Field::filter( 'choice_label', $object->$label, $this->field, $object )
    					)
    				);
    			}
    		}
    
    		public function rwmb_end_html_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {
    			if(!$depth){
    				$output .= '</optgroup>';
    			}
    		}
    	}

    It’s not beautiful, but it’s a work-around that… works!

    #8965

    pluginoven
    Participant

    Uggg… again with the markdown. Please wrap that last code in proper backticks.

    #8966

    pluginoven
    Participant

    Here are the full selectomatic custom field extended classes based on the Select field:

    if ( class_exists( 'RWMB_Field' ) ) {
    	class RWMB_Selectomatic_Field extends RWMB_Select_Field {
    		public static function walk( $field, $options, $db_fields, $meta ) {
    			$attributes = self::call( 'get_attributes', $field, $meta );
    			$walker     = new RWMB_Walker_Selectomatic( $db_fields, $field, $meta );
    			$output     = sprintf(
    				'<select %s>',
    				self::render_attributes( $attributes )
    			);
    			if ( false === $field['multiple'] ) {
    				$output .= $field['placeholder'] ? '<option value="">' . esc_html( $field['placeholder'] ) . '</option>' : '';
    			}
    			$output .= $walker->walk( $options, $field['flatten'] ? - 1 : 0 );
    			$output .= '</select>';
    			$output .= self::get_select_all_html( $field );
    			return $output;
    		}
    	}
    
    	class RWMB_Walker_Selectomatic extends RWMB_Walker_Select {
    
    		public function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {
    			$label  = $this->db_fields['label'];
    			$id     = $this->db_fields['id'];
    			$meta   = $this->meta;
    
    			if($depth){
    				$output .= sprintf(
    					'<option value="%s" %s>%s</option>',
    					esc_attr( $object->$id ),
    					selected( in_array( $object->$id, $meta ), true, false ),
    					esc_html( RWMB_Field::filter( 'choice_label', $object->$label, $this->field, $object )
    					)
    				);
    			}
    			else{
    				$output .= sprintf(
    					'<optgroup label="%s">',
    					esc_html( RWMB_Field::filter( 'choice_label', $object->$label, $this->field, $object )
    					)
    				);
    			}
    		}
    
    		public function rwmb_end_html_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {
    			if(!$depth){
    				$output .= '</optgroup>';
    			}
    		}
    	}
    }
    #9003

    pluginoven
    Participant

    Issue can be marked as resolved.

Viewing 8 replies - 1 through 8 (of 8 total)

You must be logged in to reply to this topic.