elegantthemes / create-divi-extension

MIT License
185 stars 58 forks source link

Parent / child module : access parent settings from child #110

Open MarieComet opened 6 years ago

MarieComet commented 6 years ago

Problem Description

I've a parent / child module, I need to access parent module settings from child module in get_fields function. I've tried to create a global variable in the parent before_render function, but in my child module, get_fields is called to soon, so my variable is empty. I found the get_parent_modules function but I don't know how to use it. Is there any way to access parent settings from child ? It seem to be a very basic feature...

jcdotnet commented 6 years ago

Hello @MarieComet, I was tried that with no luck either.

I want to show / hide items fields depending on a parent field, for example:

PARENT:

public function get_fields() {
  return array(
    'element' => array(
            'label'             => esc_html__( 'Element', 'plugin_domain' ),
            'type'              => 'select',
            'option_category'   => 'configuration',
            'options'           => array(
                    'optA'  => esc_html__( 'Circle', 'plugin_domain' ),
                'optB'      => esc_html__( 'Square', 'plugin_domain' ),
                'optC'      => esc_html__( 'Triangle', 'plugin_domain' )
         ),
        ),
        ....

CHILD:

public function get_fields() {
  return array(
    'triangle_option' => array(
        'label'   => esc_html__( 'Enter the triangle...', 'plugin_domain' ),
        'type'    => 'text',
        'show_if'   => array( 'element' => 'optC') // I want this field to be dependent
    ),
        ...

This would be very useful for third-party modules and I don't know if it's possible, if not I suggest these dependencies as an improvement.

MarieComet commented 6 years ago

@jcdotnet that's exactly what I'm trying to do

lots0logs commented 6 years ago

I want to show / hide items fields depending on a parent field, for example:

The ability to do that was added very recently. Its not documented yet. Here's how you would do it with your example:

public function get_fields() {
  return array(
    'triangle_option' => array(
        'label'   => esc_html__( 'Enter the triangle...', 'plugin_domain' ),
        'type'    => 'text',
        'show_if'   => array( 'parentModule:element' => 'optC') // I want this field to be dependent
    ),
        ...

Hope that helps :smiley:

MarieComet commented 6 years ago

Awesome ! Thanks you!

jcdotnet commented 6 years ago

@lots0logs How recently was it added? I'm testing with Divi 3.3.1 and it seems not work for me. I will get back to this later and let you know is something is wrong. BTW I was looking forward to this feature, I'm glad you have finally added it :) thank you!

MarieComet commented 6 years ago

Same here, not working. @lots0logs maybe when you write 'parentModule:element' => 'optC', parentModule should be replaced with parent slug, or class name ? I've tried both, child field which should be affected not showing at all.

lots0logs commented 6 years ago

IIRC, it was added in 3.4. Let me know if you still have trouble when using 3.4 or later. Also note this only works in the VB currently.

MarieComet commented 6 years ago

Ok, I didn't see that Divi was updated. I can't test now because as I said here I'm not able to use the developement mode, and debugging the VB... Using yarn build when developing is really not suitable

lots0logs commented 6 years ago

Noted. I'm going to look into the issue with yarn start asap.

jdurnil commented 6 years ago

It is not working for me what code would would i need to just grab a value from a text or say range slider like this for parent element

'num_rows' => array(
      'default'         => '0',
      'label'           => esc_html__( 'Number of Rows', 'etl-divilocal' ),
      'type'            => 'range',
      'range_settings'  => array(
              'min'         => '1',
               'max'         => '6'
        ),
       'option_category' => 'basic_option',
       'description'     => esc_html__( 'Enter in desired number of rows.', 'etl-divilocal' ),
       'toggle_slug'     => 'main_content',
),

and this for child element trying to get value from parent

'rows_span' => array(
                'default'         => '0',
                'label'           => esc_html__( 'Rows to Span', 'etl-divilocal' ),
                'type'            => 'range',
                'range_settings'  => array(
                    'min'         => '1',
                    'max'         => 'parentModule:num_rows'
             ),
                'option_category' => 'basic_option',
                'description'     => esc_html__( 'Enter in desired number of rows.', 'etl-divilocal' ),
                'toggle_slug'     => 'main_content',
            ),
mrkenng commented 6 years ago

I was trying this on the yes_no_button but could not get that to work on child. Any ideas?

'elementchild' => array(
                'label'           => esc_html__( 'Text', 'et_builder' ),
                'type'            => 'text',
                'option_category' => 'basic_option',
                'toggle_slug'     => 'main_content',
                'show_if'         => array(
                    'parentModule:parentelement' => 'on',
                ),
            ),
MarieComet commented 6 years ago

@jdurnil @mrkenng Here is a working example :

Parent :

    public function get_fields() {
        return array(
            'show_option' => array(
                'label'             => esc_html__( 'Show option', 'plugin_domain' ),
                'type'              => 'yes_no_button',
                'option_category'   => 'configuration',
                'options'           => array(
                    'off'   => esc_html__( 'Off', 'plugin_domain' ),
                    'on'    => esc_html__( 'On', 'plugin_domain' ),
                ),
                'toggle_slug'     => 'main_content',
                'tab_slug'        => 'general',
            ),
        );
    }

Child :

    public function get_fields() {
        return array(
            'content' => array(
                'label'           => esc_html__( 'Content', 'mcdt-mc-divi-tutorial' ),
                'type'            => 'tiny_mce',
                'option_category' => 'basic_option',
                'description'     => esc_html__( 'Content entered here will appear inside the module.', 'mcdt-mc-divi-tutorial' ),
                'toggle_slug'     => 'main_content',
                'tab_slug'        => 'general',
                // permet de récupérer la valeur de l'option 'show_option' du parent
                'show_if'   => array( 'parentModule:show_option' => 'on')
            ),
        );
    }

from this repo

As @lots0logs said : It's working only in the VB, not the classic editor, and you need Divi >= 3.4

MarieComet commented 6 years ago

@lots0logs now I'm looking for a way, in the VB, to set a state for each child, from a field parent value. I've tried, in the parent component :

componentDidUpdate(lastProps, lastStates) {
    if( lastProps.show_option !== this.props.show_option ) {
      const showOption = this.props.content.map( ( content ) =>
        console.log(content)
        content.setState( { itemShowOption: this.props.show_option } )
      );
    }
  }

where this.props.content is a childs modules array and this.props.show_option is a on/off yes_no_button field. But content.setState always return content.setState is not a function

here is the console.log(content) output : image

jcdotnet commented 5 years ago

@lots0logs this works in the VB as you said, but we can not use it because it throws the following exception in the console when editing in the backend:

'show_if' => array( 'parentModule:element_from_parent' => 'optC')

throws:

Uncaught Error: Syntax error, unrecognized expression: unsupported pseudo: element_from_parent
    at Function.ea.error (load-scripts.php?c=1&load[]=jquery-core,jquery-migrate,utils,jquery-ui-core,jquery-ui-widget,moxiejs,plupload&ver=5.2.1:2)

Is there a fix for this? Thank you!

cedricDevWP commented 4 years ago

Is it possible to implement this functionality for advanced fields (ex: ['fonts']) ?

here is an example of a case:

I have an on / off button allowing to display or not text in my module. If I check "no", the advanced fields to customize the text will be hidden. In my child element I would also like to show or hide these advanced fields according to the choice in the parent element.

I tried that :

$advanced_fields['fonts'] = array(
    'text' => array(
        'label'           => esc_html__( 'Text', 'et_builder' ),
        'hide_text_shadow' => true,
        'depends_show_if'   => 'on',
        'depends_on'      => array(
              'parentModule:show_text',
            ),
           'tab_slug'    => 'advanced',
           'toggle_slug' => 'fonts',
    ),
);

but not working.

nexus-mediapark commented 3 years ago

Hey, so looks like this parentModule:field just won't work for me.

For some reason I can't store the data of the dependent field. My code for parent:

'slider_type'     => array(
                'label'           => esc_html__( 'Slider Type', 'eca-eca-divi-extension' ),
                'type'            => 'select',
                'option_category' => 'basic_option',
                'description'     => esc_html__( 'Select if the slider are either a textual slideshow or a video linked slideshow.', 'eca-eca-divi-extension' ),
                'toggle_slug'     => 'main_content',
                'options'         => array(
                    'text'      => esc_html__( 'Text Slider', 'eca-eca-divi-extension' ),
                    'video'     => esc_html__( 'Video Slider', 'eca-eca-divi-extension' ),
                )
            ), 

My code for child:

           ` 'title'     => array( // Field Slug
                'label'           => esc_html__( 'Heading', 'eca-eca-divi-extension' ), // Field title/label
                'type'            => 'text', // Field type
                'option_category' => 'basic_option',
                'description'     => esc_html__( 'Input your desired heading here.', 'eca-eca-divi-extension' ), // Field Description
                'toggle_slug'     => 'main_content',
                'show_if'   => array( 'parentModule:slider_type' => 'text' ) // Field Dependency
            ),

So every time I'm adding a title to the child block the field data just won't store (after i save and refresh the field is empty).
As well var_dump($this->props['title']) always gives me an empty string;

Is there something I'm maybe missing?

mvijay63 commented 1 year ago

Hey @nexus-mediapark , any update on this issue. I'm not able to update the settings when using parentModule:field. It always return the default value. Let me know if you found any workaround for this. Thanks

Lovely-Fellow commented 1 year ago

Hey @nexus-mediapark , any update on this issue. I'm not able to update the settings when using parentModule:field. It always return the default value. Let me know if you found any workaround for this. Thanks

I'm seeing same issue.