Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preserve clojurescript objects in props #11

Open
SevereOverfl0w opened this issue Feb 24, 2019 · 3 comments
Open

Preserve clojurescript objects in props #11

SevereOverfl0w opened this issue Feb 24, 2019 · 3 comments

Comments

@SevereOverfl0w
Copy link
Contributor

I've tried a few things:

  • Just passing a clojurescript map
  • Defining a custom handler which changes attrs into {:attrs attrs} - but it was recursively changed

But haven't found a way to bypass the to-js part of hicada, this would be really useful in order to have pure clojurescript components which define an interface of some kind (in this case, taking a js object with attrs set to a clojurescript map).

I'm not sure how I would make this change to hicada exactly. It could look for metadata perhaps? But that might be a little hacky.

@SevereOverfl0w
Copy link
Contributor Author

SevereOverfl0w commented Feb 24, 2019

I've managed to invent a solution, the trick is in converting the attrs to a list, because to-js doesn't handle those.

I have a copied version of to-js-map in my project, which doesn't call to-js on vals, only on keys. Then I use a handler like so:

(fn [_ klass attrs & children]
  [klass (my-to-js-map {":my-namespace/attrs" attrs}) children])

This I then combine with a simple macro to get that key automatically out and present it as a binding.

This isn't perfect, because you lose some important things like :key, so ideally this should perform a merge.

@SevereOverfl0w
Copy link
Contributor Author

I solved the :key issue by adding some special code to to-js-map so that it would add ":my-namespace/attrs" at a top-level, but then I noticed that if I did this it would break:

(let [f #(assoc % :key (:name %))]
  (html
    [:< component (f {:name "jeff"})]))

So I wrote this js* based version as well:

(list 'js*
  "(function (prop){
     prop[':my-namespace/attrs'] = ~{};
     return prop;
  })(~{})"
  attrs
  (hicada.compiler/to-js attrs))

While it is a little bit funky, it is also pretty robust. I don't know if calling functions on props is officially supported in hicada, but this allows it to become possible in the future at least.

@niwinz
Copy link
Collaborator

niwinz commented May 13, 2021

On Penpot we have a :& special handler that just converts the first level of props to js (at compile time), this allows use this handler with our components and pass clojurescript data sturctures without converting them to js.

If there are interest, I can port it here ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants