This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-09
Channels
- # announcements (1)
- # beginners (166)
- # calva (2)
- # cider (7)
- # clojure (21)
- # clojure-dev (11)
- # clojure-italy (3)
- # clojure-russia (5)
- # clojure-spec (13)
- # clojure-uk (1)
- # clojurescript (251)
- # core-async (2)
- # cursive (14)
- # emacs (6)
- # events (8)
- # figwheel-main (5)
- # fulcro (17)
- # off-topic (8)
- # pedestal (3)
- # tools-deps (17)
According to https://clojurescript.org/guides/webpack I am trying to figure out how things like https://github.com/cljsjs/packages/tree/master/material-ui pack node dependencies to NOT require each file separately like:
@material-ui/icons/Menu
, @material-ui/icons/AccountCircle
, @material-ui/icons/Terrain
. Material-ui has also separate files for each colours etc. Dependencies like this will make webpack solution so huge with all files in only 1 dependency. Can I do something with this?
@kwladyka I don’t understand. Can’t you do what JS people do? Surely 90%+ of material-ui users rely on Webpack
In shadow-cljs I can just use ["@material-ui/icons/Menu" :default Menu]
for whatever file I need. But with https://clojurescript.org/guides/webpack I have to :
add each file to src/js/index.js
, project.clj
, and then I can require it. With 30 files from 1 dependency it will be huge.
How this https://github.com/cljsjs/packages/tree/master/material-ui work then? I don't see it import each file separately
@kwladyka yes it's a bit of work but you only have to do it once right?
There's a bit of duplication too. In cljs-spa-example adding a npm dep like router5 needs 3 changes: https://github.com/pesterhazy/cljs-spa-example/blob/master/doublebundle/library.js#L4 https://github.com/pesterhazy/cljs-spa-example/blob/master/doublebundle/package.json#L12 https://github.com/pesterhazy/cljs-spa-example/blob/master/dev.cljs.edn#L12
Figwheel Main's new npm
option (not to be confused with cljs compiler's npm-deps) autogenerates the foreign-libs stanza from your library.js. See e.g.: https://github.com/pesterhazy/cljs-spa-example/pull/4/files
So it reduces duplication down to 2x
Personally this bit of extra work is a cost I'm happy to pay for being 100% sure that any npm lib will work in my project
@pesterhazy in theory once, but in practice during developing new project many times to find right solution and dependencies (files in dependencies also).
I am trying to figure out right solution for a team. It is different then choose solution for me. People don't know all solutions and I have to be able to answer for all questions and be confident with it.
Hello clojurians
How would you store stateful JS calls like "(.dropdown js/UIkit "#id ")"
I want to use .hide() or .show() on this method
but the return value is undefined
and the dropdown won't change because it's immutable
but If I store it in an atom, how can I update it? using .show() on it only makes it undefined with (reset! the-dropdown (.show @the-dropdown))
Any help appreciated
@paul931224 you might need to get a handle on the element #id
to call those methods
I can call it, but it works only once, here is my stackoverflow question https://stackoverflow.com/questions/52237173/reagent-uikit-dropdown-use/52237355#52237355
what do you mean by getting a handle on it? @pvillegas12
Try to call (.dropdown js/UIkit "#id")
when you initialize the component, apart from the show
hide
invocations
that's what I did in the stackoverflow question, still it works only once
I have three buttons, one initializes, second shows, third hides the element
The atom route is not the way
I guess it's not, but what is the way? 😕
Try using (reagent/create-class
and implementing the :component-did-mount
lifecycle hook
call (.dropdown js/UIkit "#id")
there and in the buttons as you have it in SO
I tried that also, still the same. And if I make it from :component-did-mount
I still have to store it somewhere, so I can call .show()
on it
@paul931224 the docs https://getuikit.com/docs/dropdown#javascript apparently do not require you to store a handle to the return value of (.dropdown js/UIkit "#id")
well, that's right, and it works in chrome console, but somehow .show()
makes some state changes, because from clojurescript it doesn't work only once.
Hi All. I'm getting started with re-natal and Android (developing in Windows). After some minor struggles, I have the basic starter app running on my Android simulator. However, when I make a change to the db.cljs file (just changing the text of the :greeting), I see two warnings at the bottom of my app, instead of seeing the app contents change. I expected to see the text on the app change, but instead I got warnings like this: re-frame overwriting event handler for ...
Since I'm completely new at this, and my Google searching for this isn't turning up explanations, I'm hoping someone can explain what's happening or what I'm doing wrong.
If I close the app on the simulator and relaunch the app, I see the updated text in the greeting. But I was under the impression that I could save a code file and there would be an automatic recompile/update within the running app...
@michael_teter If you look at your namespace requires, you’ll probably see that your event handler namespace is being re-compiled because it directly or indirectly requires your db namespace. The “overwriting event handler” warning is from re-frame and is displayed as a consequence of this re-compilation. I’m speculating that the warning may be causing the other behavior your are seeing.
@mfikes I'm just getting started, so I have only done the basic first steps from the re-frame github readme. Then I make one change in the text of the greeting, and I expect my app contents to change in my simulator. So I wouldn't even know yet which file I need to perhaps change to fix a namespace problem.
This, plus the fact that the basic steps in that readme did not work, make me wish for a current tutorial or guide for doing this. I'm sure people are doing it in production (for a living even), but Google makes it look like nobody has cared about this stuff since 2016 for the most part. So I wonder if I'm facing a cliff to climb over before I can be modestly productive here...
What about other files, like those involved in the view? When you change those, do the same errors occur? Or are you able to make a change any file and see an intended effect?
@john interesting. In this basic app there are only 5 cljs files in total: 1 android specific, 1 ios, and 3 shared. It was the shared db.cjls I was changing that would cause warnings and not update the screen. However, changing the text of a button in the android specific core.cljs file did update the screen (button text)
maybe the starter app generated by re-natal is incorrect
It's possible that the place where you are changing something... doesn't expect to be changed at run time... How are you changing the text of the greeting?
Like I said, it's such a simple app that there's almost no clojure code.
It's a one page app with a text area on a view, and that text area gets its value from the db (state)
so I change the db.cljs file where it defines the value for that :greeting key
I'm so clueless here I may be wasting your time... because I find it quite odd that this appears to be setting up the views separately for iOS vs Android, and I thought surely something that's just structural view definition would be shared between both platforms.
(ns new-app.db
(:require [clojure.spec.alpha :as s]))
;; spec of app-db
(s/def ::greeting string?)
(s/def ::app-db
(s/keys :req-un [::greeting]))
;; initial state of app-db
(def app-db {:greeting "Hello blah Clojure in Android!"})
that's it
the whole db.cljs.
and you change the :greeting "hello blah" and it doesn't change?
yes it does
correct, @coinedtalk
changing that greeting value results in two warnings in the app and no display change
first warning
sorry, can't copy/paste the text 😕
wouldn't that be desired?
if I expand the stacktrace, it's quite long
but the message I posted is the final part of the stacktrace, and the previous stuff appears to be .js stuff related to figwheel communication
obviously my total lack of understanding about cljsrn is a problem here, but I have struggled to find any complete tutorial or guide
and attempting to build some of the re-natal examples has been a challenge that I gave up on. too many version differences in tooling since those demo apps were created
I don't know. I haven't messed with the repl. it's just sitting there. I only changed a file and saved it
I'm open to whatever works. It's just because some of the articles I've read that are fairly recent state that re-natal is a good way to get started with cljs and android
Well, normally you wouldn’t be repeatedly changing the initial state of your db during dev. So, while what you are experiencing is less than ideal, it is not the normal flow.
ok. So the minimal example is setup in a way that is apparently atypical
Normally, you stick your db on a defonce
and you prevent your db from reloading on changes
does anyone know anyone who writes about this stuff? I'd like to educate myself if I could find something... my search-fu has led me nowhere.
ahh I see
Well, did you find something that suggested changing the initial state of the DB and expecting it to render it? (I don’t think that is part of the normal dev flow.)
it just touted the wonders of being able to make changes to code and see them in the app without restarting the app 🙂
and since there's so little code, I picked the only text field and attempted to change it.
In the REPL upon startup it suggests making a DB change like this
(dispatch [:set-greeting "Hello Native World!"])
@mfikes my repl didn't. it said plenty, but I don't believe it suggested that.
could have been. that was long ago, and I didn't save the output of everything. I'll go make a new app and pay more attention
Here’s a copy for reference: https://gist.github.com/mfikes/059cfee98d9adba036758c2064d047ce
Thanks. I did obviously read this line from the output: "Changes you make via the REPL or by changing your .cljs files should appear live."
There are entities in the system that are hooked up to watch for changes in the DB and re-render.
I'm going to have to do some research. I'm a little surprised already that the layout is defined twice - once for iOS and once for Android. I thought the primary benefit of RN was a great amount of code sharing (pushing the unique code to just the special hardware API access). This appears to have nearly the same code in two files - one for each platform.
Anyway, I thank you gentlemen for getting me past this confusion. I should be able to stumble forward now.
Yeah, I'm guessing the react-native ecosystem partitions a bit, so they're giving you separate files to start off with
I have a fairly large app and most of it is shared code, and only a tiny bit is Android vs iOS.
but apparently. no touching db
You can change the DB’s value. Just not replace it completely. (Then you end up with a new DB.)
well, not permanently. I can dispatch in repl
that didn't seem to have any effect. same warnings as before. but now that I know not to change that file, I won't.
Maybe that's a limitation of re-natal? To get around it, you could potentially define an init namespace and function that fills up the db with some initial data after the app has loaded, then edit that fill data and it'll update your view. But it'll clobber your db if you don't structure things right.
@michael_teter There is a #cljsrn channel by the way, with folk who focus on that stack
@mfikes Ahh, I didn't see that in my list. Thanks
Willdo. It's going to be a stack-oriented task/activity tracker... something to help me remember everything else I was mid-process doing when I got interrupted and began a new task 🙂
Yep, I hate it when something urgent happens and you have to unwind your entire stack.
At least that’s what it feels like to me, as my stack is ephemeral and short-lived 🙂 Maybe I need your app.
well, I no longer work in corporate environments (offices) where I get as many interruptions. but it would be very useful when trying to show why so little gets done
because most people that come to me with a "small thing" don't realize the models in my head that evaporate while I'm helping them find their archive folder in Outlook...
Eventually there will be bells and whistles, such as stack limitations - forcing me to cancel a task that was in progress if I wish to switch to a new one.
as well as auto-canceling tasks
lots of possibilities
Here's a fun app challenge idea: Make a self-host clojurescript website that is capable of producing a downloadable static zip archive of itself, such that unzipping the archive and opening the index results in another version of itself.
Bonus points for browserifying macchiato into a service worker and turning it into a static site generator that can self generate
Guys, I really don't want to seem like a spammer but I put up my question again 😄 I have a javascript function which makes an object. I use a function on it which will change the state of the object, but the return value of the function is undefined. How do I let the function change the object so I can get the desired result? I tried to put the object in an atom, but if I want to swap! the value of it it will undefined, it is really important for my project, please help 🙂
@paul931224 Sure, what's the code look like?
I made a stackoverflow question about it, it is to be found here: https://stackoverflow.com/questions/52237173/reagent-uikit-dropdown-use/52237355#52237355
It works fine from Chrome Console, but I can't make it usable in ClojureScript, because it shows the dropdown once, but because the state is not changed in the object, it won't work for the second time, neither show() or the hide() function 😕
I insist on solving it because I feel like I will have this problem with a lot of third party javascript libraries. And because of the deadline of course 😄
Have you thrown some printlns in those handlers, to see if they're firing every time you click?
yes, and they do, I did (.log js/console "Try again"), and it got printed everytime
You're not making things easier for yourself by learning React/Reagent and using a DOM-manipulation library at the same time - direct DOM manipulation and React are polar opposite in the UI philosophy spectrum
It's possible but more of an advanced topic (in React or Reagent)
UIkit is a bootstrap library, the function what I use is to be found here: https://getuikit.com/docs/dropdown#javascript
React likes to have absolute authority over the dom elements it controls. Anything that uses an #id
is a code smell in React.
Yes, but I use both from a year now, and it works beautifully together, but there are some exceptions like my problem. And it works from Chrome Console also. I am not very good at CSS, that's why I need to use things like this for complex UI elements. Before UIkit I used http://Materializecss.com. I believe it's not bad using it on an isolated level, of course I don't delete nodes, or everwrite anything, just toggling things, making grids, animations with classes
For example I use it on this page: https://ironrainbow.hu/coating on the left side panel, on the button called "Járművek", and I just want to show and hide the dropdown with javascript, so it is not bound to the button
it works once, then I can't show it again. But the (.log js/console "Hello there")
works everytime I push the button
But, when you're at the repl, you can't programmatically .show
and .hide
the menu repeatedly?
nope, only from the Chrome Console
Is it possible to change to a different namespace just after entering a clojurescript REPL? E.g. maybe via some option through a cljs.main CLI option?
I guess my problem is related to the function not changing the object because it is immutable when I make it with (.dropdown js/UIkit "#id "). I don't think it is related to Reagent either, the comment on stackoverflow said it is related to .show() being a stateful method, and I didn't have to deal with things like this till now @john
@thiru0130 I try it meanwhile
@thiru0130 looks like repl*
takes an init-ns https://cljs.github.io/api/cljs.repl/replSTAR
I'm not sure if the latest figwheel.main or cljs.main expose a method to pass in an init-ns though
but basically, if you're willing to take some control of the repl launch process, you can control all those things
mmm, looks hard actually. I was curious to know as well so I did a little digging: https://github.com/clojure/clojurescript/blob/83866aaf597f183877c0cf586c002f3b8b51d487/src/main/clojure/cljs/repl.cljc#L953
But there appears to be a clue on how to override it further down in that namespace:
(comment
(def cenv (env/default-compiler-env))
(def aenv (assoc-in (ana/empty-env) [:ns :name] 'cljs.user))
(binding [ana/*cljs-ns* 'cljs.user]
(env/with-compiler-env cenv
(comp/with-core-cljs {}
(fn []
(source-fn aenv 'cljs.core/first)))))
)
But it'd probably be easier to user @pesterhazy's method here https://github.com/bhauman/lein-figwheel/issues/614
I thought you would need to swap! myatom (.show)
or am i missing something
but then why would it work the first time
@paul931224 yeah, I haven't seen much chatter about UIKit in here, so folks might not know what's going on with it.
@coinedtalk.show() doesn't work only called on the object made by (.dropdown js/UIkit "#my-id")
, and if I swap!
to that, it will be undefined, because the return value of .show() is undefined 😕
@john the (.dropdown js/UIkit "#my-id") makes the object, on which I can call the .show() method, which in javascript will change the object, but in clojurescript it won't because it is immutable 😕
what about (.show js/UIkit.dropdown("#category1")) 😄
my syntax is terrible but uh i think you know what i mean
You're not really using any immutable constructs when doing (.show (.dropdown js/UIkit "#my-id"))
@john my bad, so something else must be the problem 😕
@coinedtalk , john already asked that, if you are thinking about (.show (.dropdown js/UIkit "#my-id"))
😄
So what can be the problem? what is the difference between using Chrome Console, and Clojurescript Interop?
atom is reagent/atom ?
this really should work 😐
i've triggered elements like this
@coinedtalk Yes it is, I made [reagent.core :as reagent :refer [atom]], forgot to mention 🙂
Data attribute Description
data-uk-dropdown Opens the dropdown on hover and adds a little delay, so the dropdown won't disappear immediately, once you stop hovering the toggle.
data-uk-dropdown="{mode:'click'}" Opens the dropdown by clicking the toggle. The dropdown closes again on the next click.
well it is an attribute made my UIkit, so on default it is hidden. I can also make [:div {:data-uk-toggle "target: #my-id"}]
but I need javascript because I want to make more dropdowns, so when one closes, the other automatically will open, for better user experience
At least, not with out some integration. Here's something https://github.com/otissv/react-uikit-dropdown
but still, why does it work from Chrome Console then? 😕
and the :data-uk-dropdown
and :data-uk-toggle
attributes work perfectly with react, only the javascript part is messy, and only from clojurescript 😕
but it's okay, your help is appreciated anyway, at least I know it is not about immutability 😄
React sometimes ignores CSS and other stylings done outside of its scope
from what I've noticed
but it throws a warning
I can't because they are bonded to the id, that's why I usually initiate them with :component-did-mount
reagent lifecycle
But regardless, (.show (.dropdown js/UIkit "#my-id"))
should work repeatedly in a fresh repl. You gotta figure that out first.
I just got there, and it works from the repl!
so it just doesn't work from the :on-click
event?
what is the difference? 😕
it has the desired result multiple times
(defn uk-drop []
[:div
[:div#my-id {:data-uk-dropdown true} "Some content"]
[:button
{:on-click #(do (println "open") (.show (.dropdown js/UIkit "#my-id")))}
"Open"]
[:button
{:on-click #(do (println "close") (.hide (.dropdown js/UIkit "#my-id")))}
"Close"])
And when you use that? ^After every browser refresh it works once, then it doesn't, in spite of the "open" string gets printed everytime
Go to the element in your elements tab of your developer tools and go to the #my-id
object and inspect what the structures do when you click
If stuff is getting clobbered, you may have to take this route https://github.com/otissv/react-uikit-dropdown
it works the same as from the repl, but it does it only once. one show(), then one hide(), then show() won't work again, unless I use it from repl
@john okay, I will go with that, the only thing I don't understand now is the difference from starting a function from the repl, compared to an event 😄
does it change the class of the individual elements? Uikit seems to have things like class = "uk-dropdown-close" and "uk-open"
@coinedtalk yes it does, for the first time, at least from the :on-click
handler
@john well this project is one year old, I just got a bugfix list for user experience, so I have to stick to this, but I think I will write my own dropdown in clojurescript, it can't be that hard 😄
from the reagent tutorials they trigger elements like this, (.click (js/$ (reagent/dom-node this))
probably won't make a difference yeah at this point better to make your own 😄
You know, in the top level of the namespace, rub some .getElementById
s and some .addEventListener "click"
on it
@john Thank you for your time, I will try it as well! Have a good night!
@coinedtalk Well, it didn't make a difference, so I will make my own, after giving up in an hour 😄
you using uikit3?
let me know in case you figure it out, I'm working on react apps as well and want to avoid any pitfalls
yes I use uikit3 and I will, deliciousowl now in my notes 😄
@coinedtalk I solved it, by I don't know how and why. with re-frame, (dispatch [:dropdown-event])
it worked for unknows reasons
here is also another approach which I didn't tried yet, also with re-frame https://github.com/Day8/re-frame/blob/master/docs/Using-Stateful-JS-Components.md