This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-09
Channels
- # adventofcode (1)
- # aleph (2)
- # beginners (28)
- # boot (26)
- # boot-dev (8)
- # cider (10)
- # clara (10)
- # cljs-dev (130)
- # cljs-experience (1)
- # cljsrn (12)
- # clojure (118)
- # clojure-austin (40)
- # clojure-boston (1)
- # clojure-chicago (1)
- # clojure-dusseldorf (1)
- # clojure-estonia (11)
- # clojure-france (1)
- # clojure-greece (3)
- # clojure-italy (19)
- # clojure-nl (1)
- # clojure-russia (1)
- # clojure-spec (19)
- # clojure-uk (34)
- # clojurescript (62)
- # core-logic (7)
- # cursive (11)
- # datomic (35)
- # emacs (15)
- # fulcro (264)
- # jobs (4)
- # leiningen (5)
- # midje (4)
- # off-topic (74)
- # onyx (27)
- # planck (14)
- # protorepl (4)
- # re-frame (37)
- # reagent (62)
- # rum (2)
- # shadow-cljs (171)
- # slack-help (5)
- # spacemacs (6)
- # specter (9)
The Fulcro's query syntax is a subset of the Datomic's, and Datomic's pull expression support attribute navigation which can do recursive pull, such as (d/pull db e [:value {:children/ref ...}])
.
Does the Fulcro's support this syntax like {:children/ref ...}
?
:children/ref
is a join (or edge) and the ...
will be (get-query ....)
. Almost every example has this. I'm pretty sure the answer is 'no' to your second question, but only because I've never seen reverse pull used in a query.
@cjmurphy Yes, I had just tried to use {:query [:db/id {:children/ref ...}]
, and got an error 'java.lang.NullPointerExcetption`.
Always best to not do it like that, but instead have the (get-query ...)
for the subquery.
I need a tree structure for file system' folders. so if use get-query
, there will be
(defsc Folder [this {:keys [db/id folder/name folder/parent]}]
{:query [:db/id :folder/name {:folder/parent (get-query Folder)}]
:ident [:folder/by-id :db/id]})
There is syntax esp for recursion. I've never used it myself but I remember there was a blog post about it.
This stuff is pretty old: https://anmonteiro.com/2016/01/om-next-query-syntax/.
@cjmurphy Sadly, he use ...
, the code is
(defui Node
static om/IQuery
(query [this]
'[:id :value {:children ...}]))
I don't know the ins and outs of defsc
. Switch to defui
is all I can say, or wait a while till you can get a definitive answer.
fulcro is so damn hot.
@tpliliang Recursion syntax is supported, just like Datomic. You have to quote the symbols, and for defsc you have to use lambda mode:
(defsc Person [this props]
{:query (fn [] [:db/id :person/name {:person/children '...}])} ;;anybody can have children (or grandchildren)
:ident [:person/by-id :db/id]}
...)
is a legal query.
IMPORTANT NOTE: the query will work. normalization will work. UI Refresh requires that have circular refs require more effort on your part. When you render such circular data structures be sure to pass a “depth” as a computed property to children so you can tell if you need to go deeper.@tony.kay Thanks, the '...
works, even in Template Mode.
I try the reverse navigation :children/_ref
now, and want to know if the reverse thing works too.😀
reverse navigation is not supported @tpliliang
the storage format cannot efficiently process such a thing. if you want it, you have to add that explicit prop to the source entity
@thosmos The SSR got a little more refined today on that startups website project. I got the uberjar build working…had to add an additional build to get the js to work out well enough. It’s also a bit fiddly on the order of requires it seems. I had a hell of a time for about 2 hours just getting it to work…reordered some stuff and it started working again. Not my favorite dev experience 😕
@tony.kay Need help, How to use 'Link Queries'?
Why does my code always get null
?
(defsc Folder-Breadcrumb-Root [this {:keys [ui/locale get/folders]}]
{:query [[:ui/locale '_] {[:get/folders '_] (prim/get-query Folder-Breadcrumb)}]}
(js/console.log "a path" folders)
(js/console.log "ui locale" locale)
)
(def ui-folder-breadcrumb-root (prim/factory Folder-Breadcrumb-Root {:keyfn :db/id}))
Isn't this the make sure the component has a presence in the database, even if empty instruction, as described in: http://book.fulcrologic.com/#_a_warning_about_ident_and_link_queries ?
@tpliliang Have you tried logging (om/props this) ?
@U0SSNQ659 I use devcard, defcard-fulcro with :inspect true
, the database is showed well.
@U3LP7DWPR I will try now.
@U3LP7DWPR (prim/props this)
return 'undefined'
@U3LP7DWPR @U0SSNQ659 Sorry, I found the reason, I miss the appropriate definition in the :query
of (defsc Root...
Thanks.
fulcro-inspect work in index.html,but do not work in cards.html. Please give me a hint.
if you had a table that had sort order, would you put it in react component state using set-state!
?
personally would like it to show up in the state, with filters and other properties of the table. Then it would also show un in inspect & support viewer 🙂
2.1.0 seems pretty stable, so I’m taking it out of beta. Now on clojars. Has one additional fix from @mitchelkuijpers: removed a reference to a missing file that was causing problems when building with shadow-cljs
Speaking of shadow-cljs. I have not had time to try it out, but I’m really wanting to make sure Fulcro works well with it. I’ll probably play with it some in the coming weeks, but would love tips from anyone that is currently using Fulcro with it.
@thheller That’s great. I read in your blog that the cljsjs/react stuff and using js/React can cause problems.
https://code.thheller.com/blog/shadow-cljs/2017/09/15/js-dependencies-going-forward.html
yes but I now include a "migration" automatically https://github.com/thheller/shadow-cljsjs/blob/master/src/main/cljsjs/react.cljs
so if you use cljsjs.react
it just works (although you still need to manually npm install react react-dom create-react-class
)
ok. I’ll see if I can get a version of the lein template working with it, and include that as a template generation option
https://github.com/fulcrologic/fulcro-lein-template/tree/master/resources/leiningen/new/fulcro/2.x
The 2.x side in particular…there is a lot to it, though. There are serveral builds, CI integration, and i18n stuff. Probably still need project.clj, so the two need to work together
one thing that is not supported since I consider this an anti-pattern is :source-paths per build
it is totally safe to put everyone into one source path if desired. unlike CLJS we only include actually used sources in shadow-cljs builds. so if nothing requires a namespace it won’t be include in the build
@thheller so the i18n extraction is the one thing that has some additional special needs. I use the generated js to find strings (using gettext’s xgettext)
so it has to be a single js file with the original symbol names so the tool can find them
well, it might be ok…so, you can still have multiple builds, just one set of source?
e.g. an ssr build might need react.dom.server, but it would be important that the regular client mount not happen (the template does not have ssr…but I have projets that do)
I assume from your comment that this means I’d still have multiple build, just with different entry point namespaces
the closure compiler has support for extracting i18n strings, maybe that could be easily hooked up?
as far as I can tell, this won’t leverage the GNU gettext infrastructure, which I consider to be a lot more important
as for the xgettext support I can probably write an easy hook to do that automatically
that would be nice…basically, calls to tr
, trc
, and such are currently mapped to low-level global javascript functions of those names. Then a whitespace optimized js file is generated, and xgettext can run against that without modifications.
This code is part of Fulcro to run xgettext at the moment: https://github.com/fulcrologic/fulcro/blob/develop/src/main/fulcro/gettext.clj
ah its already a macro, you could instead write the strings into the analyzer metadata
trc means “with context”. Used for translating things like this (trc "The abbreviation for male" "M")
. It gives context to tre translator
so, I wrote that stuff when I was very new to clj/cljs…the reason it is a macro is I wanted compile-time error checking, and I needed the js output to be tr(“s”), not call(…)
so what you can do is (swap! cljs.env/*compiler* assoc-in [:cljs.analyzer/namespaces (-> &env :ns :name) ::strings] the-string some-info-about-string)
finally when the “build” is done collect all the namespaces that were used and merge the strings
and the file/line is also in &env, so that could make nice comments in the translator file 🙂
so how do I hook into the compiler to know when it is done (e.g. if user wants to use lein cljsbuild)
hm. not seeing anything. I like the idea, though. I guess if there was an entry point for i18n it could run a macro to emit, and require everything in the UI…that should get the order correct, right?
@thheller are you trying something possibly reusable? I don’t want to duplicate effort.
I am still struggling with how to elegantly code that a modal is hidden if form is commited successfully
@roklenarcic So, that is a bit too large of a question to answer
So I've got commit-to-entity! and I've got my bootstrap/hide-modal! mutation.
the sequence is: extract -> po files -> translator -> returned po files -> generate cljs FROM po files
@roklenarcic don’t use commit-to-entity!
…write your own, and use ptransact!
Alright. Yes that is a very valuable example to have in documentation, because a lot of people will be looking for that one.
@thheller tr
is just a map lookup against *loaded-translations*
, and the generated cljs adds to that map
@thheller The source language are the lookup keys. Yes, you can put the additional in modules.
I agree it needs some work. Again, it was very early code, and there has not been a lot of demand for improvements, so I’ve left it alone
well I guess a key is needed always anyways so might as well use the source language
right…as opposed to inventing some crap that you don’t remember what it is, and having to remember which file “those strings” are in…cross-referencing…ugh
yeah, I have distant plans for something like that…it would be pretty easy to instrument the UI automatically and let you translate against the running app
@currentoor fun project if you’re looking ^^^^ 😉
@thheller the other nice thing about using the source string: if a translation is missing, you get the default string on the screen…so the viewer has some hope of understanding what you’re saying.
the main thing I don’t like is global *loaded-translations*
(makes using more than one app on a page a pain to i18n).
how do you figure out which JS to load for which users, better to do that on load with a default language
default language comes in. You can code whatever you like in started-callback to switch locale with a change-locale
mutation
for SSR you have all available on the server, so you just pre-render with locale set…detect from browser headers or user session info
When I get time, I plan on making translations app-specific, with custom namespaces for the translations, and use something like bindings during render to put the current translations in context for tr
.
in the analyzer data you get something like [{:msg "translate me plz", :line 6, :column 1}]
for (tr "translate me plz")
bad part about the tr
call is that it emits a (get-text ...)
call which accesses an atom
so it will never be DCE’d probably
So, gettext po files are an easy format…here’s an example
msgid "string"
msgstr "translation"
Say you change a string from “Hi” to “Hello”. When you update translations msgmerge
I think also uses those comments on line/file to figure out certain things. not sure.
it would improve things to have the clj[sc]
context instead of the generated js context
On DCE: don’t care. The tr itself is very tiny, and if you don’t use i18n then you don’t call it..so there’s not much dead code to eliminate
@thheller so am I right in assuming that a macro called at the end of an entry point ns (that in turn requires all UI) could execute a different macro to affect the string output?
(ns i18n-entry
(:require-macros i18n)
(:require ui.things))
(i18n/dump-strings "i18n/messages.pot")
I don’t think the tools should care, since they work on multiple programming languages with various filename extensions…I think they just need to match on successive executions
just thinking about the extra documentation, really…I’m having a bit of writers fatigue 🙂
the sketch is shadow-cljs specific but once it works it could probably be made standalone
I think that’s how gettext does it…every mention of a particular string gets included in comment form
:test-i18n
{:target :browser
:output-dir "out/demo-i18n/js"
:asset-path "/js"
:i18n-options
{:messages-file "messages.pot"}
:modules
{:main {:entries [demo.i18n]}}}
so this file https://github.com/thheller/shadow-cljs/blob/test-i18n/src/dev/demo/i18n.cljs
ends up with a messages.pot
like
#: demo.i18n:6:1
msgid "translate me plz"
msgstr ""
might be neat if it just works when setting :i18n-options
but yeah will probably be a plugin
kinda weird that I added the context thingo half-way but the file generator looks like https://github.com/thheller/shadow-cljs/blob/test-i18n/src/main/shadow/build/i18n.clj
#: demo.i18n:6:1
msgid "translate me plz"
msgstr ""
#: demo.i18n:8:1
msgid "foo?"
msgctxt "foo"
msgstr ""
#: demo.i18n:9:1
msgid "foo?"
msgctxt "bar"
msgstr ""
(ns demo.i18n
(:require
[shadow.i18n :refer (tr trc)]
))
(tr "translate me plz")
(trc "foo" "foo?")
(trc "bar" "foo?")
plural support is done via Yahoo’s FormatJS, and I just use msgid for the format string
#: src/msgcmp.c:338 src/po-lex.c:699
#, c-format
msgid "found %d fatal error"
msgid_plural "found %d fatal errors"
msgstr[0] "s'ha trobat %d error fatal"
msgstr[1] "s'han trobat %d errors fatals"
plurals are encoded https://formatjs.io/guides/message-syntax
I do like having this built into the compiler but I’m not actually sure I want it in shadow-cljs
might be a good candidate to finally figure out the plugin API I’ve been thinking about for a way too long time now
your tool wraps the compiler, right? So, you’re basically just holding onto the compiler, running the build, then pulling this stuff out of the compiler before discarding it I assume
the macro approach I hate because its a file every use would need to write in their project
it seems an improvement over having to have a custom build and two additional external steps to run, and a command-line tool to install
so I could write a function that takes the compiler env and generates the info from that
totally forgot that I wanted to look at the lein template. will do that tomorrow I guess 😉