soflyy / oxygen-bugs-and-features

Bug Reports & Feature Requests for Oxygen
https://oxygenbuilder.com/
314 stars 29 forks source link

Attributes not rendered in HTML when using Oxygen Elements API #2071

Open titantwentyone opened 3 years ago

titantwentyone commented 3 years ago

Describe the bug Custom attributes when added do not render in HTML.

Have you tried all the steps at https://oxygenbuilder.com/documentation/troubleshooting/troubleshooting-guide/? Yes

Are you able to replicate the issue on a Sandbox install at https://oxygenbuilder.com/try? Yes - http://selfish-crossbill.w5.wpsandbox.pro/sample-page/

To Reproduce Steps to reproduce the behavior:

  1. Add a Pro Menu Component
  2. Go to Advanced -> Attributes
  3. Add relevant attributes
  4. Save and go to front end

Expected behavior Expect custom attributes to be output in HTML

What actually happens No custom attributes are output

Screenshots (https://snipboard.io/hgtQ9E.jpg) Attributes defined in backend

(https://snipboard.io/uF82Ok.jpg) Attributes not rednered in HTML

Additional context I specifically picked pro Menu here as it uses the Oxygen Elements API. The same issue can be found with Shape Dividers which also use OxyEl. Other components are created using CT_Component directly and data atttributes are sometimes rendered depending on the component as the root element is rendered along with the content (from looking at these components - some elect to use attributes and others don't). This issue specifically concerns OxyEl as it's part of the public (but not yet documented) API.

The fix seems relatively simple (AFAIK!). Attributes are passed via $options in the shortcode function in oxygen.element.class.php so we can parse and output them:

oxygen/component-framework/api/oxygen.element.class.php L154

    <?php
    $attributes = "";
    foreach($options['custom_attributes'] as $attribute) {
        $attributes .= " ".$attribute["name"].'="'.$attribute['value'].'"';
    }
    ?>

    <<?php echo esc_attr($options['tag'])?> id="<?php echo esc_attr($options['selector']); ?>" class="<?php if(isset($options['classes'])) echo esc_attr($options['classes']); echo " " . $this->params['wrapper_class']; ?>"<?php echo $attributes ?>><?php echo $html; ?></<?php echo esc_attr($options['tag'])?>>

A bit of context as to why this came onto my radar - I've been looking at the API and was wanting to experiment with making dynamic forms in the backend with Oxygen. One element I wanted to create was an "input" and I wanted to set the "name" attribute for processing. The workaround is to wrap the input in a div, forget about setting attributes on the root element and do it in the render() method however styling then effects the containing div rather than the input.

1636 - would be addressed by this

As mentioned before, because of the way other components are rendered (i.e. using CT_Component directly), this wouldn't fix all components but it would make it possible for extensions to make use of attributes in a (IMHO) better way when they use the API. Unsure if Soflyy plan on migrating all existing components to the API at some stage in which case all components which have this missing would have it resolved.

titantwentyone commented 3 years ago

Just in case anyone comes across this when developing their own components, a bit of a dirty hack is to add the attributes after render with JS:

public function render($options, $defaults, $content) {
    ?>
    <script type="text/javascript">
    jQuery(document).ready(function(){
      <?php foreach($options['custom_attributes'] as $attribute): ?>
      jQuery("#<?php echo $options['selector'] ?>").attr("<?php echo $attribute['name'] ?>", "<?php echo $attribute['value'] ?>")
      <?php endforeach; ?>
    })
    </script>
    <?php
}