How do I create components that can take positional children as arguments (Dart)?

Issue

I am looking for resources on how to make webcomponents that can take positional children arguments. Something like:

<x-editable-component>
  <span>{{value}}</span> // this could be any uneditable element
  <textarea>{{value}}</textarea> //could be any editable element
</x-editable-component>

The above element would display a span when in editable == false, and a textarea when editable == true. editable is a globally watched static variable.

I think it might be possible to get this sort of composing behavior with inheritance. However, I was wondering if it might be possible to do this in the composable fashion mentioned above. Where the component (x-editable-component) simply expects two children, one child it will display when editable, the other child it will display when uneditable.

To be clear, I want the flexibility of writing any two children as the children of x-editable-component, so maybe somewhere further down I have a x-editable component written as such.

<x-editable-component>
  <div>{{value}}</div> // this could be any uneditable element
  <input>{{value}}</input> //could be any editable element
</x-editable-component>

Is this possible?

Solution

This sounds like a great use for the <content> tag.

<element name="my-editable-component">
  <template>
    <div style="display: {{editing ? 'block' : 'none'}}">
      <content select=".editing"></content>
    </div>
    <div style="display: {{editing ? 'none' : 'block'}}">
      <content select=".normal"></content>
    </div>
  </template>
  <script type="application/dart">
    class MyEditableComponent extends WebComponent {
      bool editing = false;
      // ...
    }
  </script>
</element>

Here I’m using classes, but you can come up with whatever protocol you’d like. <content select=""> can use most CSS selectors.

This would be used like:

<my-editable-component>
  <div class="normal">{{value}}</div>
  <input class="editing">{{value}}</input>
</my-editable-component>

More information about “content” can be found on the web-ui article or you can see the example in the shadowdom spec.

Please note: I’m using display: none instead of <template if> to workaround https://github.com/dart-lang/web-ui/issues/228

Answered By – Jenny Messerly

Answer Checked By – David Goodson (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.