This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-07-12
Channels
- # admin-announcements (2)
- # aleph (2)
- # arachne (16)
- # beginners (33)
- # boot (20)
- # bristol-clojurians (6)
- # capetown (4)
- # cider (50)
- # clojure (74)
- # clojure-austin (4)
- # clojure-canada (1)
- # clojure-china (2)
- # clojure-czech (1)
- # clojure-greece (1)
- # clojure-poland (4)
- # clojure-quebec (5)
- # clojure-russia (5)
- # clojure-spec (34)
- # clojure-uk (45)
- # clojurescript (131)
- # cursive (4)
- # datascript (2)
- # datomic (9)
- # editors (2)
- # emacs (2)
- # hoplon (173)
- # jobs (5)
- # lein-figwheel (3)
- # leiningen (1)
- # off-topic (1)
- # om (44)
- # onyx (8)
- # proton (10)
- # re-frame (81)
- # reagent (23)
- # untangled (57)
- # vim (2)
- # yada (8)
@adamw: i’ve added your object tag, a way to handle bulleted lists via the markdown on the latest commit.
the markdown support is very much incomplete, a minimal implementation i tossed in quick to support of a project i needed to get out the door, but you can extend it for your purposes.
@flyboarder: it's possible but i think you need to set up the linkage in a constructor
or, make a function that takes an element, a cell, and an attribute, and syncs the cell's value to the attribute of the element
creates a cell=
that is
micha pushed up an interesting branch the other day, https://github.com/hoplon/hoplon/commit/f08d23f539c2e631be0827e17d3f7a7590c191ae
very promising i think, because it gives attributes an idea of construction
altho i suppose even in that case, the attr code wolud only know about the elem it was attached to when do! is called the first time
attrs.cljs:15 Uncaught Error: No protocol method IAttr.-dom-attribute defined for type javelin.core/Cell: [object Object]
I've put a repro into https://github.com/addplus/tpl-example
is there a way to destructure cells?
there is cell-let
which makes cells on the left side
e.g. (cell-let [[x y] some-cell] ... x and y are cells here...)
comes in handy inside -tpl
bodies
oh cool
does that work for things that aren’t cells?
actually, i don’t really understand
say i did this
(cell-let [foo (first my-cell)] …)
would that be the same as
(let [foo (cell= (first my-cell))] ..)
"soft yes"?
the idiotmatic way would be (cell-let [[foo] my-cell] ...)
@thedavidmeister: be careful when using cell-let
though. If you changed your mind about a formula cell, and decided to make it an input cell, cell-let
will still turn it into a formula cell, and you’ll get “cannot swap!/reset! a formula cell” errors.
ok cool
i didn’t know about that
(let [things (cell= [1 2 3])
x (cell= (first things))
xs (cell= (rest things))]
(cell= (prn [x xs])))
@alandipert: thanks for the info, I saw that branch but i’m trying not to go exploring right now, instead I refactored the elements a bit and changed how I was storing the state
@flyboarder: i was looking at your route-tpl while taking the train to my office. fwiw, i typically treat the route/hash just another view (and control for modifying) my application state.
flow looks something like: user clicks button -> handler updates appstate cell -> route and dom update from appstate via formula cells
or user changes route -> handler updates appstate in cell -> dom updates from appstate cell
so rather than my route being tied directly to the view, it goes through a cell first
@jumblerg: i think that’s pretty much how it works
regex-tpl
is generally for when the cell value could be any type of user input, so creating conditionals or cases may not be the most convenient method of catching everything; route-tpl
would basically wrap this plus include a (route-cell)
by making it dynamic you can redefine it be anything
so if users wanted to rebind the route cell to a new route cell they could
which i think keeps your app flow logic intact
well i’d like to provide the option for other things like vectors of keys, but generally everything would be converted to a URI path
then destructure it back via another formula cell
i’m not certain of the best approach, but i think maybe the string parsing could take place on the command side on the way into the cell/model rather than on the query side coming out.
i see what you mean, that’s probably the best place for it, I was actually thinking of wrapping cemerick/url and storing a URI in the cell
my route string is something derived from my application state, i find i need a layer of indirection there in practice
but i’ve found that dealing with it is one of the biggest challenges of creating spas
well i think it just depends on how much you want to include in the routing system and how much stays application logic
here’s how i ended up managing it in ui, from the docs, fwiw:
routing. ui treats the hash within the address bar as another part of the view; it both presents a visualization of and provides a control for changing the application's underlying view state. this state must itself be persisted elsewhere, typically within a javelin cell containing the application's model. it's no more appropriate to use the address bar as a data store than it is to use the dom for this purpose.
ui represents routes as values of the form [[:foo :bar] {:baz "barf"}], where the vector in the first position is the path and the map in the second position corresponds the query string. ui reads and writes these values via the :route and :routechanged attributes passed to window when the application is constructed. like any other attribute, :route accepts either a route or, more practically, a formula cell bound to the application model to update the route as the application's state changes. :routechanged accepts a callback that will be invoked with an updated route whenever a users enters a route different for the one being displayed into the address bar. this callback should be used to update the application's view state in the same fashion that it would be updated through any other user-initiated event, such as clicking a button.
util functions for the conversions live here, btw: https://github.com/hoplon/ui/blob/master/src/hoplon/ui.cljs#L79-L94
awesome! i was totally looking for something like those!
i think there’s a minor issue with the way it handles an empty {} atm, leaves the ? on the string.
i’m also not certain there should be a query string there at all, it kinda flat, and i’ve found in practice i want to be able to represent more complex structures
yeah I was actually thinking of making something that pulls in the query string and replaces the path with a md5hash or something so it’s always a path that im dealing with
or some other uuid of somekind
that way users can share links with cell data encoded
my cells destructure the path and get their value from the route
then you can have arbitrary state links
yeah it’s basically url minifying tied to (app) cell state
like you could even just base64 encode it
im not sure, i want it to be a user friendly string size but at the same time hold complex data
but there are two separate ideas in play here: (1) serializing the entire app state to a url and (2) encoding in a hash to guarantee integrity and eliminate redundant but semantically identical url serializations
oh goog.crypt has sha1, enjoy your workout!
usability is key
but insofar as cutting and pasting url reference to various app states is concerned, which happens much more frequently in practice, a serialized app state representation seems much more powerful.
the problem with allowing users to manually navigate app state is partial app state, what about a form that they can only see page 2 after all of page 1 is complete, so lets say someone partially fills out a form then sends their buddy a link to their current page, buddy over there is going to either lose the app state or have a broken state
@flyboarder: @jumblerg Why just do the routes outside of Hoplon with something like Bidi or Secretary?
i’m not familiar with either of those libraries, so ignorance might well be the reason. i wonder how well they would fit in with the rest of the hoplon and javelin machinery.
@tbrooke: as you can see from the wiki page doing that requires a whole bunch of boiler code
@thedavidmeister: put a bunch of examples on the wiki https://github.com/hoplon/hoplon/wiki/Pages-and-routes
https://github.com/hoplon/hoplon/pull/139 has a much simpler option using route-cell
@tbrooke: i’m looking at them now, i can’t imagine a scenario where i’d need this sort of machinery on the client, in my spa.
there’s a place, perhaps, for this sort of routing on the server if you’re exposing some sort of restful api
@jumblerg: im using firebase, all of my urls are glob matched to my spa
i’m sure there are cases for it, otherwise they wouldn’t have been written, i just haven’t found a need for this sort of thing in my own applications.
i agree i think with javelin there could be a better solution
@flyboarder: i guess i could see how it would make sense if you’re passing elements of the route through to a restful api underneath in some fashion.
yeah i think it works better for cases where your not using hoplon/javelin or castra 😛
my requests now come into cloudfront, if they’re static they go off to the S3 cache, if they’re for my service, they get passed through using representations created by castra. there’s also another heartbeat url. that’s pretty much it for me.
url pattern-matching is a lower level thing that castra has reduced to an implementation detail of the http protocol i no longer have to worry about.
it actually strikes me as a bit strange that, for almost every other protocol out there, everyone just uses libraries and remains largely ignorant of their implementations. yet for http, everyone seems to be experts in the minutiae .
maybe it's the shed, easy to have an opinion
i'm confident there isn't One Way to Route
i guess that's another way hoplon isn't a framework
@alandipert: lol routing in a nut shell, many paths you can take
yeah, if you’re a roy fielding fan, great - write a library that does it The One True Way and give me that to use.
ember?
i’m not disparaging the implementation details, they need to be worked through, i just don’t want to get caught up in them.
they've oriented their whole thing around routes, kinda like rails
i'm just grateful the path separator for URLs isn't different on windows
that would be awesome
I can deal with a leading drive character thats just a folder really
hahaha
I would also like to point out that when using the query string for cell data, this should not be a global state cell with everything in it, just things that should recover from link sharing
i don't always use windows, but when i do, it's 3.1 to play minesweeper https://archive.org/details/win3_stock
@flyboarder: Exactly what I was thinking for use with a restful API
anyone else see this? http://www.stefankrause.net/js-frameworks-benchmark2/webdriver-java/table.html
@tbrooke: so that method works if you have a backend, with firebase there is only my client app, no state to move around between the client and server
@alandipert: let’s get hoplon in there 😉
@flyboarder: I’ve looked at Firebase briefly but never thought about using it with Hoplon I’ll check it out
I am slowly shifting everything away from backends for my apps, i really like the idea of a client only app and an api only app
this fit’s in nicely with things like azure functions, where I write a single task as a function and commit to the repo, no app to build or anything
then there is a list of actions in the db with their respective url’s the db fetches a list that the user has access to based on roles, my spa then executes an action from the list using a unique name, this way I can change the urls without affecting my code, I can also mix and match api’s by changing a db value
I like to think of it like zappier but between my client app and backend api's
@flyboarder: where does the domain logic live? In azure functions?
@flyboarder: Firebase has some static hosting can you host your Hoplon app there?
@tbrooke: yes! Highly recommended! Works well with Firebase v3 API and new console. @dm3: depends on what you are looking to accomplish
@dm3: for example all of the rules for interacting with the db are on the FB DB hosting side which uploads a rules json file, when I need to interact with other API’s then its azure functions
well that depends on how your application works
@dm3 for the db specifically?
the serverless architecture seems interesting, although it's also interesting how the implementation/ops complexity scales with the complexity of the domain
i think it depends on your type of application, if you only need to store data in the db then it’s great, if you need to run server logic then youll need something like azure functions
things like a todo app can house all it’s logic in javelin cells and the root cell is just the fb db
the idea is that each function is it’s own bit of logic, they are not directly related, imho
i mean real life they will all be related to your app but i like to think of your web app as a global view of all the server bits of code I can launch, then its just buttons and webhooks
hehe, I usually start from the domain model and the UI comes out of actions that make sense given the business functions
ill have an app to show for the past few months of development soon
@jumblerg: so route-tpl was fairly easy
this is like the regex-tpl except it also supports a vector of korks