kirki icon indicating copy to clipboard operation
kirki copied to clipboard

Show/hide fields inside a repeater using 'active_callback'

Open rahulv3a opened this issue 9 years ago • 15 comments

As stated in the title, is it possible to use 'required' for fields inside a repeater? Let's say we have a select control in a repeater. Would it be possible to show/hide other fields in a repeater row according to the value of that select control?

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

rahulv3a avatar Feb 27 '16 12:02 rahulv3a

Unfortunately no, at least not yet... We have plans to do that in a future release though, so I'm marking this as a feature request. :+1:

pinging @igmoweb on this one too, as the repeater field is his creation.

aristath avatar Feb 27 '16 13:02 aristath

Any progress on this? I'd like to think this is more than needed. Required shouldn't be limited to "normal" fields! To me it's a logical approach to be able to use require within a repeater. Right now I'm asking the user to select whether to use a background image or color and present a field based on the option. Since it can't be done I now have to revert to having both and checking if an image has been set to force that to take place instead of color which is both redundant and not really good UX.

Rayken avatar Apr 18 '16 11:04 Rayken

It's on my to-do list...a long to-do list :-)

guillaumemolter avatar Apr 18 '16 13:04 guillaumemolter

Thank you. I'd be good with basically just selecting the "requirement" such as:

// background setting (image or color)
'background_setting' => array(
    'type'          => 'radio',
    'label'         => __( 'Background type', Settings::$textdomain ),
    'description'   => __( 'Background image or color?', Settings::$textdomain ),
    'default'       => 'color',
    'priority'      => 40,
    'choices'       => array(
        'color'         => esc_attr__( 'Background color', Settings::$textdomain ),
        'image'         => esc_attr__( 'Background image', Settings::$textdomain ),
    )
),

// background image (only visible if 'image' is set in 'background_setting')
'background_image' => array(
    'type'          => 'image',
    'label'         => __( 'Background image', Settings::$textdomain ),
    'description'   => __( 'Upload a background image to be used for this section.', Settings::$textdomain ),
    'help'          => __( 'Please make sure the image is at least 1920x1200 pixels.', Settings::$textdomain ),
    'default'       => '',
    'priority'      => 50,
    'required'      => array( 
        array( 
            'setting'   => 'background_setting[image]', // or simply without [image]
            'operator'  => '==',
            'value'     => true // and just have 'image' here
        )
    ),
),

// background color (only visible if 'color' is selected in 'background_setting')
'background_color' => array(
    'type'        => 'color',
    'label'       => __( 'Background color', Settings::$textdomain ),
    'default'     => '#0088CC',
    'priority'    => 50,
    'required'      => array( 
        array( 
            'setting'   => 'background_setting[color]',
            'operator'  => '==',
            'value'     => true
        )
    ),
),

Rayken avatar Apr 18 '16 13:04 Rayken

@guillaumemolter I'm guessing https://github.com/aristath/kirki/issues/906 is affecting the work on this issue. Are we going to see this implemented in the near future or is it more of a future feature at this time? If so, will a bounty help?

Rayken avatar Apr 27 '16 08:04 Rayken

@Quaked sorry for the belated response. Busy week here :-)

It was indeed kind of blocked by #906 but thanks to @aristath it should not really be an issue anymore.

If not for me a bounty might motivate someone else to have a look at it. I would love to implement this but because the repeater field is a big hack, I have the feeling that it's going to be tricky....and as I was saying above...I'm a little busy right now :-)

P.S.: @aristath @rahulnever2far can you guys edit the issue with "active_callback" instead of required.

guillaumemolter avatar Apr 29 '16 13:04 guillaumemolter

All right I think I managed to place a bounty but I'm not sure. Hopefully I did!

Rayken avatar May 03 '16 15:05 Rayken

Hey @aristath and @guillaumemolter, I've been trying to add this feature to the repeaters, however I need your help on an issue.

My first approach was to modify this line: https://github.com/aristath/kirki/blob/78e8c0e9499a601c421e161c4a6564794f75ddc0/modules/css/class-kirki-modules-css.php#L274 and check if the fields inside the repeaters have a required condition, which would look sth like this:

// Apply required conditions to repeater
if ( $field['type'] == 'repeater' ) {
  foreach` ( $field['fields'] as $repeater_field ) {
    if ( isset( $repeater_field['required'] ) ) {
      foreach ( $repeater_field['required'] as $requirement ) {
      // Compare the control value with required value

However this approach didn't work because I cannot get the index of the repeater instance in this scope so I cannot make the comparison.

My second approach was to change the repeater javascript renderer function around this line: https://github.com/aristath/kirki/blob/78e8c0e9499a601c421e161c4a6564794f75ddc0/controls/php/class-kirki-control-repeater.php#L249 and make the same comparison here like this:

<# var required = field.required; var valid = 1; #>
<# _.each( required, function( requirement, i ) { #>
  <# var requirementSetting = requirement.setting; var requirementValue = requirement.value; var requirementOperator = requirement.operator; #>
  <# if (requirementSetting && requirementValue && requirementOperator) { #>
    <# var controllerValue = data[requirementSetting].default; #>
    <# if (requirementOperator == '==') { valid = controllerValue != requirementValue ? 0 : 1; } #>
    <# if (requirementOperator == '!=') { valid = controllerValue == requirementValue ? 0 : 1; } #>
  <# } #>
<# }); #>
<div class="repeater-field repeater-field-{{{ field.type }}}" <# if ( valid != 1 ) { #>style="display:none" <# } #>>

This worked because the index of repeater instances are available here, however this rendering is made only once when the customizer is loaded, thus when the user changes a value to fulfil the requirement, the fields are not made visible until the customizer is refreshed.

Maybe I'm missing something here due to the complex nature of the repeater. Can you guys please give me a hint on either how to get the index of a single repeater instance from the php class or how to make it work with the js renderer? Thanks!

asilcetin avatar Jun 20 '18 19:06 asilcetin

This will only be possible after the 3.1 rewrite... Right now other than adding some custom JS in your theme I don't think this will be possible

aristath avatar Jun 20 '18 20:06 aristath

Hi, @aristath! Any updates on this one? Thanks!

sergeysedykh avatar Feb 24 '19 18:02 sergeysedykh

Is there anything we can help you to speed up the rewrite? A pull request for any particular bottlenecks?

sergeysedykh avatar Mar 17 '19 09:03 sergeysedykh

@classyentrepreneur I'm afraid not... The rewrite is happening and it's progressing but it's not a simple matter... First I need to finish https://github.com/aristath/kirki/pull/2083, then I need to finish rewriting the remaining controls and make it possible for all of them to be added via JS. I'll use color control as an example. The color control gets added via kirki.control['kirki-color']: https://github.com/aristath/kirki/blob/9b04dd95efc7f44ba0bd28624abf34ae6158de44/controls/js/src/kirki.control.js#L64-L122 That code passes on the control arguments to kirki.control['kirki-color'].template(), and also calls kirki.input.color.init(): https://github.com/aristath/kirki/blob/9b04dd95efc7f44ba0bd28624abf34ae6158de44/controls/js/src/kirki.input.js#L37-L91 The template gets rendered by the view in https://github.com/aristath/kirki/blob/9b04dd95efc7f44ba0bd28624abf34ae6158de44/controls/views/color.php

On the contrary, the slider control for example has 2 files:

  1. PHP: https://github.com/aristath/kirki/blob/9b04dd95efc7f44ba0bd28624abf34ae6158de44/controls/php/class-kirki-control-slider.php
  2. JS: https://github.com/aristath/kirki/blob/9b04dd95efc7f44ba0bd28624abf34ae6158de44/controls/js/src/slider.js

The new structure (the one used in the color control) allows us to simply create a new color control on the fly using kirki.control['kirki-color'].init() - and that's currently impossible in the slider control - and all other controls that have not yet been converted. Once the migration of all input types is done, a dimension control will simply be a collection of 4 text-input controls with some fancy CSS and an extra validation function. The background control won't need to be a separate control, it will simply be a collection of a color control, an upload control and a couple of dropdows or buttonsets. Similarly, the repeater control will create batches of sub-controls and the only JS it will require is the one for ordering items etc. The rewrite is slow and painful, but that's because the goal is a more versatile and modular codebase. It's a long process... but it guarantees greater flexibility and allow us to do things that were never possible before. Adding field dependencies right now to the existing implementation IS possible, but a waste of time because the whole thing will have to be written from scratch anyway. The <input> types that have already been migrated:

  • text
  • textarea
  • color
  • radio
  • select
  • number
  • image

The one one that remains from the "basic" input-types is checkbox. After checkbox is rewritten then rest of the controls are simply combinations of the above, or tweaked versions of them with some CSS & JS. For example switches & toggles are nothing but checkboxes with fancy styles, radio-buttonsets are radios and so on.

So the current plan is this:

  1. Migrate things to packages for #2083
  2. Rewrite checkboxes
  3. Rewrite remaining controls to use the new structure
  4. After all of the above is done, then and only then can repeaters start to be rewritten and allow for this - and other - features to be added.

aristath avatar Mar 17 '19 23:03 aristath

Thanks for the in-depth comment. If you need any help with a particular task, feel free to ping me and I'll see what I can do.

Thanks a lot for Kirki ❤️

sergeysedykh avatar Mar 18 '19 05:03 sergeysedykh

Hey Guys,

I've solved the active_callback inside repeaters and upload the solution in the request https://github.com/kirki-framework/kirki/pull/2368

Go to files has changed https://github.com/kirki-framework/kirki/pull/2368/files and replace in your Kirki files, You can see the files' paths from the top

If you urgently need it, DO NOT Forget to change your Kirki version to prevent from automatic update until the commit approved.

Hope it helps :)

Oxibug avatar Feb 07 '21 20:02 Oxibug

@rahulv3a @Rayken @sergeysedykh Hey Guys,

A new commit to enable active_callback in the newer version 4.x.x is available here https://github.com/kirki-framework/kirki/pull/2468

Best,

Oxibug avatar Feb 20 '22 16:02 Oxibug