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

[RFC] Remove Specular.Dom.Widgets from the main repo #31

Open
zyla opened this issue Aug 8, 2018 · 2 comments
Open

[RFC] Remove Specular.Dom.Widgets from the main repo #31

zyla opened this issue Aug 8, 2018 · 2 comments

Comments

@zyla
Copy link
Collaborator

zyla commented Aug 8, 2018

Looking at the APIs there:

buttonOnClick :: forall m. MonadWidget m => WeakDynamic Attrs -> m Unit -> m (Event Unit)

checkbox :: forall m. MonadWidget m => Boolean -> Attrs -> m (Dynamic Boolean)
checkboxView :: forall m. MonadWidget m => WeakDynamic Boolean -> WeakDynamic Attrs -> m (Event Boolean)

textInput :: forall m. MonadWidget m => TextInputConfig -> m TextInput
textInputOnChange :: forall m. MonadWidget m => String -> Attrs -> m (Dynamic String)
textInputOnInput :: forall m. MonadWidget m => String -> Attrs -> m (Dynamic String)
textareaOnChange :: forall m. MonadWidget m => String -> Attrs -> m (Dynamic String)

They are very inconsistent. Sometimes take static attributes, sometimes dynamic.

In practice I often end up writing alternate versions of them.

Maybe it would be wiser to keep them out of the main repo, and only expose:

  • facilities for binding to DOM events of DOM nodes
  • (maybe) facilities for binding to value of DOM nodes

@dktn @przembot Opinions?

@przembot
Copy link
Contributor

przembot commented Aug 8, 2018

(maybe) facilities for binding to value of DOM nodes

That would correspond to some event changed of DOM node?

Overall, maybe yes, but it would end up writing some commons every time and sticking to them.
What kind of facilities can you think of?

zyla added a commit that referenced this issue Mar 19, 2019
## Motivation

The current DOM building API doesn't scale in the number of options added to the element, such as:
- no attrs/static attrs/dynamic attrs
- event handlers/`input` handling
- attaching extra libraries to the node (Material Components, for example)

Each dimension requires adding a whole set of functions covering the previous dimensions. So the total number of functions is exponential in the number of dimensions.

A good example of this problem is #31:
- multiple versions of the same widget
- some widgets take `Attrs`, some `Dynamic Attrs`, some none

## Solution

Unified element creation API:

```purescript
el :: forall m a. MonadWidget m => TagName -> Array Prop -> m a -> m a
```

`Prop` is now _the_ mechanism to provide additional dimension. Examples of `Prop`s:

```purescript
attr :: Attrs -> Prop
attrD :: Dynamic Attrs -> Prop
```

These are the ones provided for now. In the future we'll have something like:

```purescript
onClick :: Effect Unit -> Prop
onClickPreventDefault :: Effect Unit -> Prop
```

for event handling.

"Higher-level" widgets can take an `Array Prop` for customizing its inner DOM elements, allowing the same level of control as when manually defining them.

External libraries like Material Components can be provided using a similar API:

```purescript
-- | Attach a MDCRipple component.
mdcRipple :: Prop
```

This way we can use all of these things at once easily:

```purescript
el "button" [attr ("class":="save-button"), onClickPreventDefault handleClick, mdcRipple] do
  text "Save"
```

## Caveats

1. `el "div" [attrD ..., attrD ...]` will have surprising results if the two sets of attributes overlap.
2. We can't use `Specular.FRP.Event`-based API for events. In our current usage of Specular we don't do that anyway.

## Performance comparison

Note: the goal here is not to be faster than the old API. But we can't be slower.

The same widget rendered using different APIs. See `bench/Bench/Builder.purs`.

```
old - elAttr    x 8,294 ops/sec ±2.66% (60 runs sampled)
old - elDynAttr x 3,724 ops/sec ±1.07% (64 runs sampled)
new - attr      x 9,285 ops/sec ±1.31% (63 runs sampled)
new - attrD     x 5,846 ops/sec ±1.37% (34 runs sampled)
```

So not only it's not slower, but seems noticeably faster.
@zyla
Copy link
Collaborator Author

zyla commented Nov 11, 2019

Related: #33

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