This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-03-03
Channels
- # admin-announcements (2)
- # beginners (18)
- # boot (118)
- # cider (12)
- # cljs-dev (12)
- # cljsrn (24)
- # clojure (142)
- # clojure-art (4)
- # clojure-bangladesh (3)
- # clojure-ireland (1)
- # clojure-italy (7)
- # clojure-norway (4)
- # clojure-poland (207)
- # clojure-russia (101)
- # clojurescript (108)
- # clojurewerkz (2)
- # core-async (6)
- # css (8)
- # data-science (23)
- # datomic (31)
- # devcards (2)
- # emacs (8)
- # funcool (25)
- # hoplon (34)
- # immutant (78)
- # ldnclj (7)
- # lein-figwheel (4)
- # leiningen (6)
- # luminus (35)
- # off-topic (1)
- # om (119)
- # onyx (43)
- # parinfer (29)
- # proton (11)
- # re-frame (25)
- # remote-jobs (1)
- # slack-help (1)
- # spacemacs (3)
- # yada (10)
@anmonteiro: In your Routing in Om Next post, you have a mutate function alter the query for your root component; does this mean that you're attaching functions to the onClick properties of dom elements in your components (as opposed to using something like secretary or bidi)?
@futuro: This is function you can yourself call in the onClick event callback. You have to configure bidi/secretary yourself. You should look at https://github.com/kibu-australia/pushy which supports both bidi and secretary.
@tawus: yeah, I was curious if @anmonteiro had made that choice or not. I'm guessing they did, but I hadn't considered that approach until now.
specifically, it seems like they've completely bypassed history in general in their post, but I'm not certain
There is a lein template from @anmonteiro where the history has been taken care of. https://github.com/anmonteiro/aemette.
I'm trying to make a keyboard shortcut for an Om Next component. Basically, I'd like a component instance's handler function to be called whenever a key press is registered. I found a library for doing this with pure react.js: https://github.com/Chrisui/react-hotkeys I suppose I could use this with JS interop; however, I'm curious if people with more experience with Om Next have any suggestions of how to go about doing this?
Really, all I need to do is to bind a key which -- when pressed -- changes the reconciler's app-state via a (om/transact ..)
Since component's are a function of the app-state, I should be good
Any suggestions on how to do this (i.e., bind a keypress to a call to (om/transact! )?
@george.w.singer: Check out KeyboardShortcutHandler
in Google Closure. Then just use the normal lifecycle react methods
@rauh: brilliant suggestion! I had no idea this was stock a Google Closure concern.
I presume I would follow the instructions here (but use cljs JS interop): http://www.andrewnoske.com/wiki/JavaScript_-_Shortcut_Keys#Setting_up_KeyPress_Events_using_Closure
Would all of the stuff shown in that code snippet be within the component class definition (made via the defui
macro)? Then, when a keypress is registered, it would call a method defined within the component class definition?
Here is the code snippet that I'm talking about:
goog.require('goog.dom');
goog.require('goog.events.KeyCodes');
goog.require('goog.ui.KeyboardShortcutHandler');
function showTriggered(event) {
alert('Shortcut triggered: ' + event.identifier);
}
var shortcutHandler = new goog.ui.KeyboardShortcutHandler(document);
var NONE = goog.ui.KeyboardShortcutHandler.Modifiers.NONE;
var CTRL = goog.ui.KeyboardShortcutHandler.Modifiers.CTRL;
var SHIFT = goog.ui.KeyboardShortcutHandler.Modifiers.SHIFT;
var ALT = goog.ui.KeyboardShortcutHandler.Modifiers.ALT;
var META = goog.ui.KeyboardShortcutHandler.Modifiers.META;
shortcutHandler.registerShortcut('A', 'a');
shortcutHandler.registerShortcut('T E S T', 't e s t');
shortcutHandler.registerShortcut('SHIFT_F12', 'shift+f12');
shortcutHandler.registerShortcut('CTRL_A', goog.events.KeyCodes.A, CTRL);
shortcutHandler.registerShortcut('ENTER', goog.events.KeyCodes.ENTER);
goog.events.listen(
shortcutHandler,
goog.ui.KeyboardShortcutHandler.EventType.SHORTCUT_TRIGGERED,
showTriggered);
@george.w.singer: This is how i used it to listen on an escape: https://gist.github.com/rauhs/ec1a7b94a6481ae4cf1d
@rauh: Thanks for your help. Very nicely laid out. Going to study that example for my own use case.
@rauh: the only thing I don't understand about your code snippet is what the #(goto % (route-home))
trigger function is doing. Is goto
a component class method that you're calling?
@george.w.singer: That's just the action you want to perform when ESC is pressed. In my case I route to home.
Does it have to be through goto
? Or is that just a dummy function that you're using in this case?
More specifically: could I replace #(goto % (route-home))
with #(myComponentMethod ..)
?
@rauh: nevermind. Calling component methods works fine.
@futuro: integrating with broswer history is orthogonal to routing, so I didn't include it in that post
Are there any examples of entirely client side uses of Om?
@grounded_sage: The quick start and other articles on the wiki.
Things are relatively straightforward until you start dealing with remotes
Ok I'm just more of a full example kind of guy. Been building a static site with Stasis, Garden and Hiccup following Atomic Design principles but it's become very fragile and complex workflow (I haven't even touched any JS yet!). Was thinking about using either Om or Reagent for the next website I need to build. I was told to just use Plain React, I don't want to spend time learning Webpack etc. Then I was told I could just use the script tag and use it without NPM. Though I have mixed feelings about using anything other than Reagent of Om for the website.
just take any example you can find and ignore the remote parts
the whole point of om is that it's easy to separate this stuff
but i'm not sure it really fits your use-case, if you're after a static site
surely there are better options for that
@grounded_sage: The kanban demo is a full example that's client-side only.
That would be great if you could @cjmurphy my Clojure chops aren't quite ready for Boot Though I still will check out that example as I would love to learn Boot.
@iwankaramazow: turns out there were tons of places in my app that had perf problems, most of them very little to do with Om Next. I tore my app down to simple use cases and it appears that I can use Om's default DB format fine. (I started experimenting with my own DB format but I kept noticing other places where I was doing something stupid)
@iwankaramazow: it simplifies things a lot as well if I deal with batches of 1000 items, and no more. So 1000 items will load, and if you scroll all the way down and hit the bottom it'll load 1000 more. Om can handle batches of this size perfectly fine
Thank you @cjmurphy
@iwankaramazow: And I'm using VirtualScroll to optimize the displaying of them. I tried using InfiniteScroll
which loads things on demand as you scroll but it's way too easy to produce too much network chatter
I am trying to read transit data from a cljs backend targetting nodejs/expressjs. Consider the following POST function on the backend (in expressJS):
(. app (post "/read" (fn [req res]
(.dir js/console (t/read (t/reader :json) (aget req "body"))))))
This function is trying to read the transit data sent from the client within the req.body
object. Yet this returns the error: `"SyntaxError: Unexpected token ~"
Yet if I *stringify* the result, and then try to print it to the console, I get what is clearly transit data:
(. app (post "/read" (fn [req res]
(.dir js/console (t/read (t/reader :json) (JSON/stringify (aget req "body")))))))
The value printed to my console from that is ["^ ","~:remote",["~:images/list","~:dir/current"]]
So how can I get cljs-transit to convert the transit data from req.body
into a cljs persistent data 褧tructure?I earlier declared (.use app (.json bodyParser #js {:type "application/transit+json"}))
in my code. I'm wondering if the issue is there? If I take out the ":type "application/transit+json"" bit, then req.body
isn't even populated with a value.
@george.w.singer: don't use the json bodyParser, express is trying to parse it as json
I have (.use app (.text body-parser))
and then I POST it with a Content-Type of text/plain
@jlongster: what does your client POST look like?
(POST "/read"
{
:response-format {:content-type "text/plain"}
:params (t/write (t/writer :json) clj-data-to-send)
:handler (fn [res] (.log js/console (cb (t/read (t/reader :json) res))))
:error-handler error-handler})
I tried adjusting to .text
on the backend as you suggested, and used that snippet above^ on the front-end. It's still not working(defn post [url data]
(let [ch (chan)]
(xhr/send
url
(fn [e]
(put! ch (.getResponseText (.-target e))))
"POST"
data
#js {:Content-Type "text/plain"})
ch))
When I attempt to read the response on the back-end via
(.dir js/console (t/read (t/reader :json) (aget req "body")))
I'm getting this printed to my console:
{ meta: null,
cnt: 1,
arr:
[ { ns: null,
name: 'remote',
fqn: 'remote',
_hash: null,
'cljs$lang$protocol_mask$partition0$': 2153775105,
'cljs$lang$protocol_mask$partition1$': 4096 },
{ meta: null,
cnt: 2,
shift: 5,
root: [Object],
tail: [Object],
__hash: null,
'cljs$lang$protocol_mask$partition0$': 167668511,
'cljs$lang$protocol_mask$partition1$': 8196 } ],
__hash: null,
'cljs$lang$protocol_mask$partition0$': 16647951,
'cljs$lang$protocol_mask$partition1$': 8196 }
Am I correct to be reading req.body
? Is that where the transit data is at?
@george.w.singer: that seems correct, it's a CLJS data structure
if you print with println
you might get a more readable thing
That worked
@jongster: Thanks for pointing me in the right direction. I think you're the only other person I know who uses clojurescript/node on the backend instead of clojure lol
Is there a way to express for this component, always use the :db/id prop as the ident
?
@jannis: Do you mean as a shorthand?
Instead of having to implement Ident
?
Implementing Ident
let's you do just that (ident [this {:keys [db/id]}] [:items/by-id id])
, but you already knew that
As a shortcut. Imagine all your data being entities from e.g. Datomic or DataScript and they all have a :db/id
, you'd have to write the same (ident ...)
in all components.
But what would be the first element in the ident?
Would have to be different for all
Anyways, I don't think David is up for customization stuff like that, so I wish you luck 馃槈
Yeah, sounds like something you could easily do yourself outside om
Similar to having to add #js for om/dom attributes, there are lots of things like this that could be made slightly more convenient. I tend to agree that they don't need to be integrated into om.
I want to use in my app both react-with-addons
and bootstrap-cljs
. But when in my code I call a bootstrap function, I get in the browser an error: ReactBootstrap is not defined
. It seems to me that the problem is that in order to use react-with-addons
I had to exclude the regular react package in my project.clj
: [org.omcljs/om "0.9.0" :exclusions [cljsjs/react]]
. Am I correct? Is there a way around it?
anmonteiro: Well, if you use something like DataScript, all entities are uniquely identitifed by their :db/id
. So you can safely use [:db/id (:db/id props)]
for all components and have no clashes.
@danielstockton: Yeah, you can do it if you wrap defui in a new macro for instance.
defuident 馃槈
I'm also aware that a lot of commercial projects that are picking up Om Next want to use DataScript in the client and they'll all face the same situation.
i count myself in the datascript group, there are other problems that are bigger atm
like having no solution to set-query!
@jannis: makes sense, but I also tend to agree that customization falls out of Om's scope
Also, you might want another attribute than db/id even when using datascript. You can't update db/id, so how can you deal with optimistic mutations for example?
I think at the very least, these kind of conveniences should be added when other more important things are settled and it becomes much clearer how everyone will use it.
Hi Guys - I鈥檓 looking to use set-query! to change the query parameters of a component, but from a different component. Is this possible?!
I do it all the time from my repl when developing
(om/set-query! (om/class->any reconciler Component) :stuff)
tony.kay: the todo mvc example repo seemed to indicate it was tried.. https://github.com/swannodette/om-next-demo/blob/master/todomvc/src/cljs/todomvc/parser.cljs#L16
@tony.kay: I think I've tried it with a very simple thing at some point
what problem are you having?
java.lang.IllegalArgumentException: No implementation of method: :-find-sources of protocol: #'cljs.closure/Compilable found for class: nil
oh.. haven't bumped into that
I'm a bit busy now, I'll try it on my side when I can and let you know
I copied the settings from om-next-demo, and now I get a different lovely error: java.lang.UnsupportedOperationException: nth not supported on this type: Symbol
@tony.kay: I tried it real quickly once and it compiled somehow, but it didn't run (some minification error). I assumed it was my fault with some 3rd party lib
why would it not work with optimized mode? it's all CLJS so shouldn't it work by default?
When recursively calling parse, If I return a remote, how do I get om to call send on that remote? Since the result of the recursive parse call is only the :value there is no :remote in the top level parse call.
Found it. Duh...accidentally had something quoted that came from code, but is now in project.clj
Ok. got it, there is a third argument to parse that specifies target. The return value is then the :target instead of :value.... sorry for the noise
Now back to: java.lang.IllegalArgumentException: No implementation of method: :-find-sources of protocol: #'cljs.closure/Compilable found for class: nil
It did work, BTW, but I copied stuff from David's configs. For anyone interested, here is what I have:
@tony.kay: have you tried without externs?
I think that's something from the past which is not needed
because Om ships with its externs atm
@tony.kay: one more thing: use :elide-asserts true
in your advanced build to strip out Om invariants
@anmonteiro: Yeah, that seems ok too