Yeah, I am experimenting with limitations and arrays came up so I have some prototype support.
view foo = view`<div style="display: flex">
<table>
${["r", ['r1', 'r2'].map(r => {
return view`<tr>
<td>${Inputs.range([0, 10])}</td>
</tr>`
})]}
</table>
</div>
`
should give you foo.r. But I don't have support of that array dynamically expanding.
Maybe join https://d3js.zulipchat.com/#narrow/stream/273880-ui/topic/Observable.20UI.20Design.20Guidlines.20and.20linter
I am playing with more advanced stuff here (including an array) https://observablehq.com/@tomlarkworthy/view-examples
I am waiting a little bit for everything to settle before documenting the next iteration.
Tom:
Consider the following two cells:
Cell 1:
viewof buttons = view`
<div>${["button1", Inputs.button("Button1")]}</div>
<div>${["button2", Inputs.button("Button2")]}</div>
`
Cell 2:
{ buttons.button1;
return new Date()
}
Clicking 'button2' will mutate buttons; resulting in Cell 2 to re-evaluate.
Is this the intended behavior?
this is expected behaviour, if you want finer grained notifications of just button 1, without involving dataflow from buttons, you can reference the subview as "viewof buttons.button1"
I don't know a way of triggering ***dataflow*** from that without an intermediate variable, but there are other methods for get change notifications like bind, or addEventListener
Inputs.bind(..., viewof buttons.button1)
Note often you only need bindOneWay which gives you the ability to transform the value enroute, which is what your code is doing so cell2 can be expressed equivalently as:
bindOneWay(
Inputs.text({ disabled: true }),
viewof buttons.button1, {
transform: (_) => new Date()
}
)
sorry my version of cell2 is a view not a simple cells so its not quite equivalent but nearly (i.e. the variable name plain 'cell2' will act the same as it did before)
viewof cell2 = bindOneWay(
Inputs.text({ disabled: true }),
viewof buttons.button1, {
transform: (_) => new Date()
}
)
For reference you can trigger fine grained dataflow with some rearrangement:
create an authoritative view like:-
viewof cell2 = Inputs.input({});
and then binding to it within the subview
view`... ['subview', Inputs.bind(..., viewof cell2)]`
Now changes in the UI are transmitted to cell2 via view synchronization and you can selectively hear a specific control through dataflow off the upstream authority cell
ah yes, there is no additional variable to hold the value so if it is reevaluated it always takes it from the subnode, which might have changed... good one.
This appears to add quite a few static dependencies to other notebook modules which are loaded even when they aren't referenced:
- @tomlarkworthy/testing
-- @tomlarkworthy/reconcile-nanomorph
--- @observablehq/htl
-- @severo/import-uuid-and-nanoid
-- @tomlarkworthy/serverless-cells
Would you consider lazy-loading @tomlarkworthy/testing instead? I'd be happy to prepare a suggestion if you're open to that change.
Ahh, yeah the core notebook is light but all those dependencies come from "testing". It would make sense to lazy load this. If you look the notebook, it only runs tests if the href includes "href.includes('@tomlarkworthy/view')" (see viewof suite cell) so the decision to lazy load the module would make sense there too. In general, I was a decent pattern for not shipping testing code with production, as quite a few notebooks I find are actually running tests on import and all kinds of weird stuff I don't want.
The philosophy:
When I am viewing the notebook I am developing and I want to run tests reactively. When I import the notebook functionality I am using it as a library (it's production intent) and I do not want to ship test code where possible (and I particularly don't want to run tests!).
You can drop the else block after the `if(singleton)` check because `if(singleton) { return ... }`. That's one less indentation level and might make that Prettier formatting a tiny bit more digestable :)
(done)
yes this is in desperate need of a refactor. I have noticed what I am conflating is Object/Array/Scalar variants of a view builder. They have different logic and state but I have them all in the same scope.
The nicest thing would be to split them up into seperate functions with unique scope. (singleton == scalar). I am trying to document the spec in the tests and build up enough test cases for a refactor down the line. I don't have many tests for the scala functionality though.