Skip to content

Custom grouping components with nesting issues

JessicaOPRD edited this page Nov 3, 2021 · 2 revisions

Problem

Many native HTML elements and CSS frameworks expect a direct nesting order such as:

<table>
  <tr>
    <th>Column A</th>
    <th>Column B</th>
  </tr>

  <tr>
    <td></td>
    <td></td>
  </tr>
</table>
<div class="row">
  <div class="col-6"></div>
  <div class="col-6"></div>
</div>

Wrapped in custom components, the structure becomes less intuitive:

<op-gallery>
  <div class="row">
    <op-gallery-image>
      <div class="col-1">
        ...
      </div>
    </op-gallery-image>
  </div>
</op-gallery>

This can interfere with intended nesting styles or even default layout behavior. Not every component-based framework has an "easy" or intuitive fix. Below are some fixes for reference when moving between frameworks.

Workarounds

AngularJS

Note that AngularJS did once support a replace property on the component definition, to be used in conjunction with transclude. This has been deprecated.

Apply ng-transclude directive using attribute form, not tag form

This will likely only prevent some nesting in a grouped scenario, but everything helps. Instead of:

<div class="row">
  <ng-transclude></ng-transclude>
</div>

Attempt:

<div class="row" ng-transclude>

Add classes to the root $element passed to the constructor (link/controller)

There may be another way to do this, but the strategy works in applying expected style classes to the outer root element:

function RadioChipInput($scope, $element, $attrs, ctrls) {
  $element.addClass('.col-1');
}

Resulting structure

<div class="row" ng-transclude>
  <op-gallery-image class="col-1">
    ...
  </op-gallery-image>
</div>

Wrap the root element's children in a new tag via the compile function

As shown on Stack Overflow.

function(tElement, attrs) {
  var content = angular.element('<div class="row"></div>')
  content.append(tElement.children());
  tElement.replaceWith(content);
}

Testing what this does?

Clone this wiki locally