TypeRocket / core

TypeRocket core source files where all the magic lives.
https://typerocket.com
36 stars 21 forks source link

Add conditional logic API #23

Closed zackphilipps closed 4 years ago

zackphilipps commented 5 years ago

The API works like this:

echo $form->radio('choices')->setOptions([
  'Choice 1' => 'choice-1',
  'Choice 2' => 'choice-2'
]);

echo $form->text('conditional field')->setConditions([
  [
    [
      'field' => 'choices',
      'value' => 'choice-2'
    ]
  ]
]);

You can combine arguments in the "inner" array(s), which creates an AND relationship, or you can add arrays to the "outer" array to create an OR.

echo $form->text('conditional field')->setConditions([
  [
    [
      'field' => 'choices',
      'value' => 'choice-2'
    ], // this is an AND
    [
      'field' => 'example',
      'value' => 'example'
    ]
  ], // this is an OR
  [
    [
      'field' => 'example',
      'value' => 'example'
    ]
  ]
]);

If all the conditions evaluate to true, the field will be shown.

For the field argument, the API ignores nesting/prefixing within groups, repeater, builder, and matrix, but prefers fields that are closer to the affected field in the DOM. So, there is no need to include brackets or dots in your field. If you have a field with the same name that is farther away from the field you want to toggle, you must rename it. To facilitate this, the API searches within "groups" of fields of decreasing proximity. Here is the order of precedence:

  1. Repeater row
  2. Tab panel
  3. Builder component
  4. Meta box
  5. #wpbody (the main WP admin content element)

The API does not care, however, if you have a hidden field and a shown field with the same name. It will always save the value of the displayed field and ignore the hidden one.

kevindees commented 5 years ago

@zackphilipps

How would this work with repeater fields?

Thanks, Kevin

zackphilipps commented 5 years ago

not 100% sure what you mean, but have a look at the getOuterWrapper function here which prefers repeater rows to every other field "group"

zackphilipps commented 5 years ago

also should i include commits like these in TypeRocket/typerocket? https://github.com/TypeRocket/typerocket/commit/0248575303569b79a62872dd93aa534d4e93be4f

kevindees commented 5 years ago

Hey @zackphilipps

Can you write some documentation for this feature with examples?

Thanks, Kevin

zackphilipps commented 5 years ago

@kevindees I updated my first comment with more detail and pushed a couple of small updates. Let me know your thoughts.

zackphilipps commented 5 years ago

As I'm reading this I'm realizing that I could allow for dot notation and that would be a better solution than forcing others to rename fields... Then again the splat in repeater.*.subfield is slightly odd. I initially had this implementation outside of TypeRocket so I was a bit limited. What do you think? Is the juice worth the squeeze?

zackphilipps commented 5 years ago

@kevindees on second thought, the current implementation allows for greater portability if you want to abstract a "group" of fields. Consider the following use case:

function bg_color_field( $form, $name = 'Background Color' ) {
  return $form->select( $name )->setOptions(
    [
      'Dark Gray' => 'dark',
      'Light Gray' => 'light',
      'White' => 'white'
    ]
  )->setSetting( 'default', 'white' );
}

function text_color_field( $form, $name = 'Text Color' ) {
  return $form->select( $name )->setOptions(
    [
      'Dark Gray' => 'dark',
      'Purple' => 'purple'
    ]
  )->setSetting( 'default', 'dark' )->setConditions([
    [
      [
        'field' => 'background_color',
        'value' => 'white'
      ]
    ],
    [
      [
        'field' => 'background_color',
        'value' => 'light'
      ]
    ]
  ]);
}

function color_fields( $form ) {
  return $form->row(
    bg_color_field($form),
    text_color_field($form)
  );
}

(the conditions are on the text color field)

Appreciate any thoughts you have on the matter. Because of the need to add the setConditions method to the Field object, our only options are to edit core directly or wait for this to be merged.

zackphilipps commented 5 years ago

Implemented via macros for now.

galingong commented 4 years ago

What's up with this? I can't find any info on the feature, nor am I able to use it the way it's described. Also setConditions method missing from Field.php. @zackphilipps last comment contains broken link, what do you mean, by macros?

kevindees commented 4 years ago

@galingong

This feature is not a part of Open v4. However, Pro v1 does have this feature. I wanted to add this feature to the free version but it did not have the underlying structure I wanted to make it work in a robust way. Zack's work here significantly inspired the Conditional fields in Pro.

You can see the feature comparison here:

https://typerocket.com/compare-versions/

Note that Pro and Open do not use the same code base.

Thanks, Kevin