This project doesn't have a concrete road map. It's in the experimental stage
right now. This md
is just a list of problems whose solutions haven't been
implemented or even figured out.
For a few of these, I haven't decided whether they are problems Strawberry should be solving. In keeping with the theme of simplicity, there are ways around the problems, but they might feel convoluted.
Ultimately this framework should feel intuitive and simple even if it is at the cost of not being able to do everything.
Terminology:
- Reactive Data Object (RDO): the object received when
sb.init
is called, when props of this object are updated, the UI updates.
List
- Setting
sb-*
props for Strawberry inserted elements - Directives for Strawberry Created Elements
- Logic Encapsulation in Templates
- Interactive Elements in Templates
- Animating
sb-if
- Two-way Binding (SKIP)
- Nested Components
- Defer Directives
Problem if I have a list of a
elements which is added by strawberry
<!-- Invalid strawberry but gets the point across -->
<div sb-mark="links" sb-child="a"></div>
<script>
data.a = [{ name: 'Example', link: 'example.com' }];
</script>
there is no way to set the href
attribute.
A Solution to this is to have a directive that sets attributes. This along with the nested components is a solution.
<div sb-mark="links" sb-child="a">
<a sb-mark="links.#.name" sb-attr-href="links.#.link"></a>
</div>
<script>
data.a = [{ name: 'Example', link: 'example.com' }];
</script>
Problem is when an element is created and inserted by strawberry, there is no way to init the properties of that element.
This is more of a enhancement than an issue, should strawberry even do this.
Problem is that scripts inside templates run in the global context. And if the template is external, they don't run.
This means that templates can't have logic ascribed to them.
Problem is that templates can have multiple interactive elements, inputs, buttons, etc. But accessing these elements requires traversing the Shadow DOM.
Problem is that when sb-if
causes a elements to be removed it's done using
el.replaceWith
which is not animatable.
Problem is that currently when an RDO prop is set in a regular script
tag
<script>
const data = sb.init();
data.prop = 'value';
</script>
only the elements before the script with the apt sb-mark
are updated.
Downstream elements are not updated.
Desired behavior is that all elements are updated. Irrespective of the where the script is loaded.
A solution is that when RDO props are set inside the head
tag, the updates
are deferred until the ready state changes to "interactive"
. This happens only
after the DOM has been parsed but before all assets have been fetched.
Problem is that currently sb-mark
on plain elements don't support nesting.
For instance say I have a nested list:
data.list = [
[1, 2],
['a', 'b', 'c'],
];
Where I want the outer list items to be rendered in a ul
and the inner ones
in an li
.
<section>
<ul>
<li>1</li>
<li>2</li>
</ul>
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
</section>
if the number of items in the outer list or inner list were fixed, it is possible to create templates with digit slot names:
<!-- If the inner list has a fixed number of items -->
<template name="example-list">
<ul>
<li>
<slot name="0"></slot>
</li>
<li>
<slot name="1"></slot>
</li>
</ul>
</template>
or just by using sb-child
:
<!-- If the outer list has a fixed number of items -->
<ul sb-mark="list.0" sb-child="li"></ul>
<ul sb-mark="list.1" sb-child="li"></ul>
But for nested lists with a varying number of items it is not possible without using JavaScript. This is without even considering the nesting depth.
A solution is to allow sb-mark
items to have children that define the
shape of the child:
<section sb-mark="list">
<!-- ul used for the outer list -->
<ul>
<!-- li used for the inner list -->
<li></li>
</ul>
</section>
This has the added advantage that the markup can be filled with placeholder data
until the actual data loads. And to indicate that these are sb-child
elements,
they can be marked like so:
<section sb-mark="list">
<ul sb-mark="list.#">
<li sb-mark="list.#.#">loading...</li>
</ul>
</section>
Note: this prevents "#"
from being used as a valid RDO prop name.
Problem is sb-mark
can't be used on input elements to change their
value when the RDO prop changes, or vice versa.
Solution is writing a new directive for this:
const data = sb.init({
directives: {
bind({ el, value, parent, prop }) {
el.value = value;
el.oninput ??= (e) => {
parent[prop] = e.target.value;
};
},
},
});
This is trivial, but the question is
- Should this be in strawberry?
- Should this be incorporated into
sb-mark
when element is an input element?
Probably not considering, two way binding can be:
- lazy: i.e. using a
change
listener - delayed: assignment takes place only after a time
So, instead of inserting the batteries—in the spirit of simplicity—this probably won't be added in.