hoplon

The :hoplon: ClojureScript Web Framework - http://hoplon.io/
2018-01-30T01:21:19.000102Z

@hiskennyness mmm how do we write that though...

flyboarder 2018-01-30T01:22:09.000342Z

@thedavidmeister I use a dynamic state variable and rebind when I want to create a local state scope

2018-01-30T01:22:56.000087Z

what does that look like?

flyboarder 2018-01-30T01:23:16.000248Z

(ns degree9.state)

(def ^:dynamic *data* (javelin.core/cell nil))

flyboarder 2018-01-30T01:28:27.000182Z

(ns other.ns
   (:require [degree9.state :as state]))

(defn mkstate [input]
   (binding [state/*state* (data.ns/get-data)]
     (let [...]
         ;;everything in here that has a cell which referenced state/*state* we get scoped data, this lets us create consistent state cells
      )))

2018-01-30T01:30:06.000400Z

why not just make a fn that returns a new data cell?

2018-01-30T01:31:17.000363Z

also i meant "how do we write that in a convincing way on the homepage" ๐Ÿ˜›

flyboarder 2018-01-30T01:31:23.000343Z

thats what get-data does

2018-01-30T01:31:24.000011Z

but this is interesting

2018-01-30T01:33:42.000074Z

i don't really use binding so i'm wondering what the advantage is over just passing cells into fns as args

flyboarder 2018-01-30T01:34:05.000120Z

runtime binding

flyboarder 2018-01-30T01:35:06.000294Z

some state has to be bound at runtime, also you get state-isolation between elements in -tpl

flyboarder 2018-01-30T01:35:49.000041Z

but hoplon also has itโ€™s own runtime binding in the hoplon.binding ns provided by @micha

2018-01-30T01:37:00.000368Z

i don't think i've run into issues with state not being isolated

flyboarder 2018-01-30T01:37:03.000211Z

you also get to modify โ€œnestedโ€ state without directly passing it around

2018-01-30T01:37:15.000175Z

i think i need an example of the problem before i understand the solution

flyboarder 2018-01-30T01:39:06.000352Z

https://github.com/flyboarder/blaze

flyboarder 2018-01-30T01:39:38.000116Z

for example @thedavidmeister ^

flyboarder 2018-01-30T01:40:10.000245Z

in that example config is binding+`let`

flyboarder 2018-01-30T01:41:56.000090Z

the best example on that page is probably how the router works, there is a router which can be dynamically bound so all the components use the router but dont actually care what it is implemented by, the implementation is bound at runtime

2018-01-30T01:42:47.000436Z

right so you're setting *admin-menu* to a cell somewhere near the top of your app's tree structure

2018-01-30T01:42:55.000314Z

then all the children can use it if they want

flyboarder 2018-01-30T01:43:10.000370Z

right without passing the variable around

2018-01-30T01:43:17.000117Z

hah, not sure if i love it or hate it ๐Ÿ˜›

flyboarder 2018-01-30T01:43:42.000372Z

there is a common api which all the components agree on, ie the core โ€œstateโ€

2018-01-30T01:43:57.000071Z

yeah

2018-01-30T01:44:06.000222Z

so it is very convenient from an app perspective

2018-01-30T01:44:12.000115Z

but would make things less portable from a lib perspective

flyboarder 2018-01-30T01:44:31.000138Z

sorta, the idea is you build App domains around it

2018-01-30T01:44:51.000241Z

well if you went and stuck

2018-01-30T01:44:54.000126Z

(defelem card-button [attr kids]
  (let [id (:id attr *admin-menu*)]
    (div :id "card-admin-button" :class [:mdl-button--admin_button-container]
      (btn/button :id id :fab true :class [:mdl-color--primary]
        (i :class [:material-icons :mdl-color-text--white] "more_vert"))
      (menu/menu :top-right true :data-mdl-for id
        (menu/menu-item "Admin Item")))))

flyboarder 2018-01-30T01:44:56.000235Z

so libraries are wrapped within a ns, then you implement a namespace per provider

2018-01-30T01:44:57.000132Z

into a lib

2018-01-30T01:45:05.000201Z

i have to manage a *admin-menu*

2018-01-30T01:45:13.000256Z

multiply that by a few dozen libs and it would be annoying

flyboarder 2018-01-30T01:46:34.000192Z

the blog was a good example of how quickly the bindings can grow and be annoying but the cool thing is that you get the ability to swap state providers at a single site instead of throught an application simply by including the ns and replacing the binding

2018-01-30T01:46:55.000283Z

yes, well my approach is just passing everything through

2018-01-30T01:47:26.000205Z

because i got burned by my app having lots of "reaching out" to state inside hoplon elements

2018-01-30T01:47:33.000110Z

so i did a big refactor

2018-01-30T01:47:45.000005Z

but i can see a few places where it would be convenient to use your binding approach

flyboarder 2018-01-30T01:47:47.000035Z

yeah thats what I usually do too, this was mostly an experiment, I dont know the runtime costs of doing all this rebinding

2018-01-30T01:47:57.000287Z

well for me it was about testability

2018-01-30T01:48:07.000158Z

but the binding approach can satisfy that i think

2018-01-30T01:49:00.000142Z

for example, i have a project-id that lots of things use, and it comes from the route

2018-01-30T01:49:14.000026Z

that could be a binding

2018-01-30T01:50:26.000030Z

it makes sense to me when you have app-specific components that are deeply nested and rely on info derived directly from things that are already inherently global, like the route

flyboarder 2018-01-30T01:52:20.000046Z

@thedavidmeister we could make running the tests as simple as binding the provider

flyboarder 2018-01-30T01:53:45.000110Z

(binding [hoplon.test/*provider* hoplon.jquery]
   (require [hoplon.test/*provider*]))

2018-01-30T01:54:02.000092Z

oooh

flyboarder 2018-01-30T01:54:02.000217Z

and calling all the tests with a function we can wrap

2018-01-30T01:54:42.000033Z

yeah, or is there like a "before hook" that we can call once?

2018-01-30T01:54:47.000168Z

for the whole suite

flyboarder 2018-01-30T01:55:30.000090Z

yeah thats kinda what is possible with the elem! pr

2018-01-30T01:55:50.000124Z

cool, will it work in cljs though?

2018-01-30T01:55:54.000382Z

i don't think require is a fn in cljs

2018-01-30T01:55:56.000294Z

only clj

flyboarder 2018-01-30T01:55:56.000332Z

since elem! implements invoke you can override it

flyboarder 2018-01-30T01:57:00.000241Z

but I dont think we can do much at compile time without either a macro or compiler var

2018-01-30T01:58:37.000307Z

i do wonder if we'll need providers forever...

2018-01-30T01:58:54.000193Z

seems like a lot of what hoplon does should be supported by browsers in a reasonably standard way

2018-01-30T02:00:42.000020Z

or maybe we just namespace the "extra features" from the provider at the attr level

2018-01-30T02:01:21.000147Z

would :jq/click be the worst?

2018-01-30T02:02:38.000108Z

i'm not 100% sold on the approach of pulling in a namespace and having that implicitly rewire all the core internals

2018-01-30T02:02:57.000195Z

again, it makes writing and sharing libs harder

flyboarder 2018-01-30T02:03:20.000377Z

I dont think we need the to do anything implicitly

2018-01-30T02:03:35.000139Z

we already do though

2018-01-30T02:03:54.000259Z

(:require hoplon.jquery) implements a whole bunch of stuff

flyboarder 2018-01-30T02:04:00.000241Z

well only the โ€œextraโ€ features

2018-01-30T02:04:02.000272Z

as soon as it is included it changes how core works

2018-01-30T02:04:21.000260Z

yeah, what i mean is that if i write an app and use hoplon.jquery all the way through

flyboarder 2018-01-30T02:04:31.000160Z

that could easily be fixed by prefixing the current provider attributes

2018-01-30T02:04:35.000253Z

then i want to split out some cool functionality into a lib, then how do i do that easily?

2018-01-30T02:05:01.000348Z

i wouldn't be confident that it works with any old provider, because i can't test that

2018-01-30T02:05:15.000373Z

and i wouldn't want to include hoplon.jquery because then i'd blow away whatever provider you were using

flyboarder 2018-01-30T02:05:39.000195Z

yeah vendor prefixes are probably a standard we should implement since the support has been around since v7.0

2018-01-30T02:05:48.000193Z

mmm

2018-01-30T02:06:00.000165Z

i mean look at us scratching our head over just testing core's own functionality

2018-01-30T02:06:18.000034Z

way harder to take that into the wild for random libs floating around

2018-01-30T02:07:23.000225Z

and things like adding/removing attributes, adding event handlers, basic DOM manipulation, triggering events...

2018-01-30T02:07:29.000224Z

all that shouldn't need a provider

2018-01-30T02:07:50.000098Z

if you want a :toggle go ahead and use jquery as :jq/toggle

2018-01-30T02:08:07.000157Z

if you want to add a class to an element, well that should just be a simple fn call in core

flyboarder 2018-01-30T02:09:35.000023Z

@thedavidmeister yeah the basics are provided by hoplon core already, but most events arnt provided

2018-01-30T02:09:45.000346Z

well yes and no

2018-01-30T02:09:54.000055Z

they are provided but then they get blown away when you pull a provider in

2018-01-30T02:10:17.000024Z

which you inevitably have to do because events

2018-01-30T02:12:51.000239Z

@flyboarder i'll put a tx up, we can come back to this at some point ๐Ÿ™‚

2018-01-30T02:18:47.000074Z

@hiskennyness mind if i paste what you said into the github thread?

flyboarder 2018-01-30T02:34:31.000017Z

yeps

flyboarder 2018-01-30T02:34:43.000093Z

i mean go for it

flyboarder 2018-01-30T02:34:48.000026Z

๐Ÿ˜›

2018-01-30T03:13:00.000056Z

changing the way providers work is not a BC change, so i'm thinking a candidate for an 8.0 release...

kennytilton 2018-01-30T08:37:05.000232Z

@thedavidmeister Search me. ๐Ÿ™‚ How many folks have even coded up an FSM in anger? I think these spreadsheet and FSM analogies work only after a series of concrete examples have manifested the elegant effectiveness of dataflow. Then we go big with the parallels to spreadsheets and FSMs. I am trying to catch my tendency to explain dataflow to myself, who already has experienced its power and is trying to understand it. Those explanations are rationally sound but viscerally unbound.

kennytilton 2018-01-30T08:44:02.000673Z

@thedavidmeister Yes, posting to the GitHub thread will be fine.

2018-01-30T09:40:38.000496Z

@hiskennyness the localness of the scope and independence of components is good, also "programming with values" rather than "programming with time" is good

2018-01-30T16:33:02.000130Z

"programming with time" i like it, as the opposite of programming with values