Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

discussion: Conditional Fields #14

Open
matepaiva opened this issue Jun 13, 2021 · 7 comments
Open

discussion: Conditional Fields #14

matepaiva opened this issue Jun 13, 2021 · 7 comments

Comments

@matepaiva
Copy link
Owner

I was thinking in a good semantic way of matching Conditional Fields with GraphQL. Something like that:

{
  institutionalContents {
    nodes {
      title
      excerpt
      action { # this name comes from set_conditional_logic.field 
        ... on NewsletterSubscribeAction { # this name comes from set_conditional_logic.value + set_conditional_logic.field
          textFieldPlaceholder
          textFieldLabel
          buttonText
        }
        ... on LinkAction {
          href
          label
        }
      }
    }
  }
}

The idea is using Inline Fragments, grouping fields with the same set_conditional_logic within the same Carbon Container. I don't know if it is a good idea so I want to know your opinion. In the case above, the carbon fields would be something like that:

      Field::make('select', 'action', 'Ação')->set_options([
        'link' => 'Link',
        'newsletter_subscribe' => 'Newsletter Subscribe',
      ]),
      
      // Link
      Field::make('text', 'href', 'href')->set_conditional_logic([['field' => 'action', 'value' => 'link']]),
      Field::make('text', 'label', 'label')->set_conditional_logic([['field' => 'action', 'value' => 'link']]),

      // Newsletter Subscribe
      Field::make('text', 'text_field_label', 'text_field_label')->set_conditional_logic([['field' => 'action', 'value' => 'newsletter_subscribe']]),
      Field::make('text', 'text_field_placeholder', 'text_field_placeholder')->set_conditional_logic([['field' => 'action', 'value' => 'newsletter_subscribe']]),
      Field::make('text', 'button_text', 'button_text')->set_conditional_logic([['field' => 'action', 'value' => 'newsletter_subscribe']]),

Please have a look @Mooxdesign @ojohnny @moxxuk @benada002 :)

@matepaiva matepaiva changed the title Discuttion: Contiditional Fields discussion: Contiditional Fields Jun 13, 2021
@benada002
Copy link
Contributor

I'd find such an interface a great addition. But I'd also add the value of set_conditional_logic to the interface. Like:

{
  institutionalContents {
    nodes {
      title
      excerpt
      action { # this name comes from set_conditional_logic.field
        conditionalLogicValue # this comes from set_conditional_logic.value
        ... on NewsletterSubscribeAction { # this name comes from set_conditional_logic.value + set_conditional_logic.field
          textFieldPlaceholder
          textFieldLabel
          buttonText
        }
        ... on LinkAction {
          href
          label
        }
      }
    }
  }
}

@matepaiva
Copy link
Owner Author

@benada002, the conditionalLogicValue would be more or less the same as the __typename of the Inline Fragment, wouldn't it?

@benada002
Copy link
Contributor

Yes, you're completely right. But I think in case your logic is based on a boolean value it would be kind of nice to have it. Or how are planning on handling a boolean value?

@benada002
Copy link
Contributor

benada002 commented Jun 14, 2021

Or if you want to show the value somewhere (I don't know how likely this situation is) but in this case you'd have to clean __typename to use it since the field name is also included in the __typename, right?

@matepaiva
Copy link
Owner Author

Oh, I see. Because it's actually overriding the action field (in the example). Maybe we could avoid overriding it nesting all conditional fields in conditionalFields?

Other thing that I am not sure is how to handle when set_conditional_logic has other properties, for example:

Field::make( 'text', 'crb_facebook', 'Facebook URL' )
    ->set_conditional_logic( array(
        'relation' => 'AND', // Optional, defaults to "AND"
        array(
            'field' => 'crb_show_socials',
            'value' => 'yes', // Optional, defaults to "". Should be an array if "IN" or "NOT IN" operators are used.
            'compare' => '=', // Optional, defaults to "=". Available operators: =, <, >, <=, >=, IN, NOT IN
        )
    ) ),

@benada002
Copy link
Contributor

If you're using an interface (https://graphql.org/learn/schema/#interfaces and https://www.wpgraphql.com/functions/register_graphql_interface_type/) I don't think you need nesting. I also belive a reason field is a better choice, because then you would also get the right type?!

Is your second concern more about the __typename length if you join it together, and it would have multiple rules (like for the example in your comment: CrbFacebookAndCrbShowSocialsYesAnotherFieldNameAnotherValue)?

@matepaiva
Copy link
Owner Author

Sorry, I have to step back a bit because I think my initial concept is wrong. To expose the GraphQL query below, I should not use conditional fields. I should use complex fields with multiple groups.

{
  institutionalContents {
    nodes {
      action {
        type: __typename
        ... on InstitutionalContentActionLink {
          href
          label
          style
        }
        ... on InstitutionalContentActionNewsletterSubscribe {
          label
          style
        }
      }
    }
  }
}

So the query above would be something like this in carbon fields:

Container::make('post_meta', 'Configurar ação')
    ->where('post_type', '=', $post_type)
    ->add_fields([
      Field::make('complex', 'action', 'Ação')
        ->set_required(true)
        ->set_max(1)
        ->add_fields('link', 'Link', [
          Field::make('text', 'href', 'href')->set_attribute('placeholder', '/assine-agora ou https://...'),
          Field::make('text', 'label', 'Texto')->set_attribute('placeholder', 'ex.: Assine agora'),
          Field::make('select', 'style', 'Estilo')
            ->set_options([
              'primary' => 'Primário',
              'secondary' => 'Secundário',
              'tertiary' => 'Terciário',
            ])
            ->set_default_value('primary')
        ])
        ->add_fields('newsletter_subscribe', 'Assine à newsletter', [
          Field::make('text', 'label', 'Texto')->set_default_value('Assine agora'),
          Field::make('select', 'style', 'Estilo')
            ->set_options([
              'primary' => 'Primário',
              'secondary' => 'Secundário',
              'tertiary' => 'Terciário',
            ])
            ->set_default_value('primary')
        ])
    ]);
});

That said, I don't think we actually need to create anything special for set_conditional_logic. My bad for introducing the idea. It's not necessary to expose the set_conditional_logic because they have nothing to do with the front-office, they are only used to handle back-office logic. For instance, set_conditional_logic is not exposed via REST.

Although we could create a way to expose automatically the container above as a query. For now I am making it by hand and it's ok because it's a small project, but I think it could be a great improvement in this plugin.

I am using the code below to expose it by hand today:

add_action('graphql_register_types', function () use ($post_type) {
  register_graphql_object_type('InstitutionalContentActionLink', ['fields' => [
    'label' => ['type' => 'String'],
    'href' => ['type' => 'String'],
    'style' => ['type' => 'String']
  ]]);
  register_graphql_object_type('InstitutionalContentActionNewsletterSubscribe', ['fields' => [
    'label' => ['type' => 'String'],
    'style' => ['type' => 'String'],
  ]]);

  register_graphql_union_type('InstitutionalContentAction', [
    'typeNames' => [
      'InstitutionalContentActionLink',
      'InstitutionalContentActionNewsletterSubscribe'
    ],
    'resolveType' => function ($institutionalContentAction) {
      $type = $institutionalContentAction['_type'] ?? null;
      switch ($type) {
        case 'link':
          return 'InstitutionalContentActionLink';

        case 'newsletter_subscribe':
          return 'InstitutionalContentActionNewsletterSubscribe';

        default:
          return '';
      }
    }
  ]);

  register_graphql_field('InstitutionalContent', 'action', [
    'type' => 'InstitutionalContentAction',
    'resolve' => fn ($institutionalContent) => carbon_get_post_meta($institutionalContent->ID, 'action')[0] ?? null
  ]);
});

@matepaiva matepaiva changed the title discussion: Contiditional Fields discussion: Conditional Fields Feb 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants