Fork me on GitHub
#fulcro
<
2018-06-30
>
thosmos05:06:02

I'm about to embark on a fairly complex data editing backend with many forms, subforms, etc. The app is currently based on Fulcro 2.5.3. I'm curious if you think using the fulcro bootstrap or semantic-ui approach would be better? I'm inclined to use SUI since I've never used it before...

cjmurphy08:06:01

From my reading of the documentation (dom/div :.div.col-sm-2) and (dom/div {:classes [:$div :$col-sm-2]}) should do the same thing. But for me the first one works while the second doesn't.

tony.kay13:06:11

Only localized dom has support for the :classes key

tony.kay13:06:01

and it interprets them in the context of the localized component

cjmurphy13:06:24

I see, the co-located Fulcro CSS, whereas I have the CSS loaded in the standard way, on the index.html page: <link rel="stylesheet" href="css/bootstrap/bootstrap-3.2.0.min.css">

tony.kay13:06:23

that notation is handy, though, and should probably be adopted into regular DOM…just have not had the time. I particularly like the idea of making it ignore nil, so that you can send in a class that should appear/disappear via an expression:

(dom/div {:classes [(when hidden? :.hidden)]} ...)
I’m pretty sure that made it into the localized dom version, but as keywords (not strings)…not sure which is better for plain dom (keywords or strings), since there is no ambiguity…probably both are fine

cjmurphy13:06:13

Thanks. I have to use plain dom as am doing a translation from a pre-React ClojureScript SPA.

tony.kay13:06:47

You can use the localized DOM functions and just use $ instead of .

tony.kay13:06:30

but they have more overhead

cjmurphy13:06:51

I doubt that a little overhead will be my greatest concern. Or at any rate not my concern at the moment...

tony.kay13:06:25

Since your actively using them, I’d be willing to generate a quick snapshot that would support :classes in regular DOM elements. I don’t think it is terribly hard to add, and I’ve been wanting it myself 🙂

tony.kay13:06:58

if you’re willing to try it out and let me know of problems that would help me feel better about coding it quickly 😉

cjmurphy13:06:58

Yes of course. I'm going to be using quite a bit of hiccup, as that seems to work fine, and was a requirement for this project. But I know I can use either on a per component basis, and that the differently rendered components compose together perfectly.

tony.kay14:06:02

2.5.12-SNAPSHOT

tony.kay14:06:25

pretty heavily tested, so it should be good on client and SSR

OliverM09:06:16

@thosmos I'm using Bootstrap 4 via Reactstrap in a very similar scenario. You can use the BS4 classes directly with fulcro's dom fns which is very handy, and reactstrap covers the cases where some js-level implementation is needed (or you could re-implement that yourself, though I haven't found the need to yet)

OliverM09:06:40

Reactstrap's coverage of Bootstrap isn't perfect but any issues I've had have been resolved by using Bootstrap classes directly

OliverM09:06:47

The one bugbear is that using reactstrap breaks SSR without some sort of stub classes for use server-side being made. You'd have that with SUI too, but not with Fulcro's own Bootstrap3-based stuff.

tony.kay13:06:54

@thosmos I’m a fan of semantic UI’s CSS. The react implementation is rather large, though I’ve had reasonable luck with the components working. That said, I like having access to clean SSR without running a js engine on the server, so I prefer just using the CSS in my own components for most things. When it comes to a more complex component that has a lot of logic I sometimes punt and make a function that will at least be “ok” with SSR (the cljs side will use some ecosystem js thing, and the clj side will emit some static representation that will largely ignore props and just output something “acceptable” for that initial inactive render). I wanted a autocomplete control recently, and I tried 3 different js versions (including SUI) before just hand-coding my own logic in Fulcro with SUI CSS. I spent like 10 hours trying to get the others to work (the way I wanted), and about 5 getting my own written. This has been my experience a number of times: getting what I want often is faster to just code my own. The CSS is the big time suck when implementing most of these things, and having a pre-written solid CSS library is, IMO, the real important bit. That said, I usually do still try ecosystem stuff when I know it is going to take me hours to write it. Unfortunately, I don’t “give up” and write my own quickly enough sometimes.

tony.kay13:06:07

The bootstrap namespace in Fulcro is probably going to move to its own library with some other less-known stuff. I don’t have the time to maintain it, and don’t use those bits myself. I wrote them as a proof of concept really, and they should really have their own “maintenance” library. If you’re going to rely on me for maintenance of them, then you will likely be sadly disappointed. That said, there’s nothing to them, so they are “safe” to adopt in that they are a starting point, and you could contribute to maintain them from there.

thosmos14:06:59

@oliver.mooney @tony.kay thanks for the great tips! Since this is a backend app SSR is not needed.

tony.kay14:06:51

I just pushed 2.5.12-SNAPSHOT to clojars with a DOM convenience:

(dom/div :.a {:className "other" :classes [(when hidden "hidden") (if tall :.tall :.short)]} ...)
is now supported on normal DOM elements (client and SSR tested). Waiting on a trial in a large app before officially releasing.

8
tony.kay14:06:43

the :classes allows you to more easily use expressions, and will silently drop nil results…it isn’t much different that str, other than it participates with the keyword shortcuts.

tony.kay14:06:23

the above tag, assuming (not tall) and hidden, would yield CSS classes “a other hidden short” on the output

tony.kay14:06:22

It technically also allows muliple classes per keyword in :classes, but that is just a side effect of using the same parsing as the props-prefixed classes.

tony.kay14:06:10

NOTE: This is similar to a feature localized-dom already had, but localized dom localizes the keywords to the component being rendered.

tony.kay15:06:15

use . not $

tony.kay15:06:20

$ is for localized dom, to mean “global”…in regular dom, it’s just like hiccup

tony.kay15:06:58

strings are ok too…I’ve tested it pretty well, and released 2.5.12 to clojars

cjmurphy15:06:19

Works fine for me: (dom/div {:classes spacer-classes}), where spacer-classes [:.div :.col-sm-3] in the surrounding let form.

tony.kay15:06:35

I don’t think you’ll run into any problems. I tested the macros, functions, embedded things in dev cards, etc. I think it’s pretty solid.

cjmurphy15:06:44

I tried spacer-classes ["div" "col-sm-3"] as well, works too

tony.kay15:06:06

nil is elided, so you can use when expressions to good effect

tony.kay15:06:21

:classes [(when hidden? :.hidden)]

tony.kay15:06:09

I’ve been wanting the feature for some time, so thanks for motivating me to finally add it 🙂

simple_smile 12
cjmurphy15:06:14

Yes spacer-classes (when false ["div" "col-sm-3"]) worked as well.

cjmurphy15:06:40

, in that I could see the CSS wasn't being applied.

tony.kay15:06:17

I meant expressions within the vector of classes

tony.kay15:06:32

but nil for :classes works too

cjmurphy15:06:08

Right yeah I just tested something else 😉

currentoor17:06:44

@tony.kay if you have a moment, i'd really appreciate a quick sanity check for my modal approach https://clojurians.slack.com/archives/C68M60S4F/p1530299846000275 is this how you are doing modals in semantic ui?

tony.kay17:06:12

I put modals at the root, so that they are aria compliant …at least that’s why I think it is done that way

tony.kay17:06:21

then use mutations on the modal to hide/show

tony.kay17:06:41

also sometimes use a union to choose modals when I need different renderings

tony.kay17:06:36

At the moment I think I’m actually using SUI react’s component for modals and letting it deal with it 🙂

currentoor19:06:42

but doesn't that mean you pull in all of SUI? or is there a way to only pull in one component?

claudiu21:06:17

Tried pulling in just a few (shadow-cljs importing dist/commonjs/button). Not a lot of benefit... Just button pulls in a large portion of code ( including ~100kb of lodash).

currentoor00:07:32

yeah seems like i'll just make my own modal component in the root

currentoor21:06:23

also, thanks for the feedback simple_smile