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
Use scala-dom-types #62
Conversation
@cornerman I've addressed some of the issues in raquo/scala-dom-types#1 I didn't have the time to test it with my own projects yet, but it should work. One thing that I still haven't resolved yet is how to deal with naming collisions. To outline the problem:
I haven't yet checked how many collisions like this exist – it's kinda hard because Scala DOM Types listings were originally borrowed from ScalaTags, which specifically doesn't have all the attrs / props because of name conflicts, e.g. ScalaTags does not have a I'm not yet sure how to address this, but this seems like something that should be addressed at the Scala DOM Types level. Not including such basic things as a Some of the potential solutions:
I kinda like this approach because it will be very flexible – you don't need to use ExtraKeys trait if you don't ant to, and you're free to bundle ExtraAttrs and ExtraProps any way you want. However, using ExtraKeys will require users to specify
I'm definitely open to ideas & feedback on this. |
@cornerman Oh, one other issue is how Scala DOM Types deals with Styles (I mean the The way it's implemented right now, I think you will need an implicit conversion from Scala DOM Types' |
@raquo Nice, thank you for working on this. The changes for the builders look good to me; will try it out later! For the styles, I can live with the current design, it should be doable with an implicit conversion as you say. The advantage of doing it like ScalaTags is that the implementations are similar and fixes on one side can be merged easier. I'll let you know if I have a better idea. |
@raquo Another question regarding boolean attributes: In html there are two different kinds of boolean attributes. Quoting from the HTML5 spec: "A number of attributes are boolean attributes. The presence of a boolean attribute on an element represents the true value, and the absence of the attribute represents the false value." But, for example draggable is not a boolean attribute, but an enumeration of In outwatch, we therefore have two different builders for attributes with boolean values. One that emits a boolean value and another one that emits a boolean value as a string. Thereby, we can hand the value downstreams and snabbdom will decide how to render the attribute depending on the type of the value. Attributes with a boolean value (strictly equal to true or false) will be rendered as boolean attributes. In scala-dom-types, both kinds of attributes are handled with a boolean value and there is no way on our end to decide which builder to use. Any ideas how to handle this? How do you do it? For example |
I haven't had a lot of time to look at all of what this PR has to offer, but I'd just like to say thanks for all of your efforts, all of you! Scala-dom-types definitely seems like a great library (so does Laminar btw) so I hope we can leverage it |
@raquo Maybe another option for (not) handling conflicts in dom-types: This mentions that changes to attributes are always synced into the properties and vice versa ("with some exceptions"). Also when using pure html, I am never confronted with these kinds of conflicting names, because html only has attributes. Styles are also not conflicting as they live inside their own attribute (style="..."). So, maybe we should not even mix Attributes and Properties together? When constructing html, I just want to use attributes. Only for the special cases (like input.value - are there others?) we need to explicitly set the property when updating the attribute (like done in outwatch code). But this is another story and does not affect the dom types. It only suggests, that using only attributes is enough. So, the option would be to just leave scala-dom-types traits as is and let them conflict. In outwatch, we could just mixin the Tags, Attributes and Events. For the Properties and Styles, we would just have a trait and an object. And you can inherit, import and shadow values as you like. In the normal use case, the |
@cornerman Re: pseudobooleans – Interesting quirk. A few ways to deal with it that I see:
Maybe we could do something similar for attributes – just add another
( Or maybe even limit availability of that second method to only boolean attrs, but that seems a bit overkill?
I think I prefer option (3). Would this work for Outwatch? If so, do you need / want the implicit evidence? There's another issue lingering here – if you set draggable to true, how do you "unset" it – not set it to false, but rather remove the attribute altogether to get the "auto" value? I think the answer is not specific to these pseudo-boolean attributes, it should be some other method in the same place where I will have more time in a couple days to think and implement this. |
@raquo Thanks for the response, I would also prefer option (3). I think an implicit evidence would be cool to limit the availability of this function - as it is only applicable for boolean. So, I think this should work for outwatch. For the other options, I do not really like to switch the type of the attribute, as it is still a boolean. The difference lies in the attribute and not in the value I am assigning (i.e. With regards to the "unset"-issue. At least for outwatch, I do not see a problem. Snabbdom handles this for us already and interprets attributes with boolean values correctly. The value "true" creates an attribute without value and the value Btw. how do you currently handle this in snabbdom? |
@cornerman I ended up implementing this a bit differently, in a way that lets you differentiate boolean vs enumerated attrs by either type or implementation (or both), and without requiring implicits. There's a new I've now added proper typings for boolean / enumerated attrs, and also for all aria attrs.
I was not aware of this pseudoboolean attrs problem, so it must be broken. I'll fix it in Snabbdom.scala after publishing a version of SDT that makes this distinction. |
116dbce
to
99b0b20
Compare
99b0b20
to
e3fd5fe
Compare
I just rebased this PR on master. @LukaJCB since a lot of code got removed, please check that we didn't remove any custom outwatch attributes you introduced (like |
@raquo Thank you so much! This is really nice to use now. One more point: We are currently using As of now, we have just added an additional builder |
@cornerman I've actually renamed |
Oh, and I will also rename |
e3fd5fe
to
95435fc
Compare
@raquo |
95435fc
to
70dd6fa
Compare
9b2ddf9
to
5d8ecc6
Compare
I just rebased this branch on top of master. Everything compiles and the tests pass. (If one published The next step is to port it to "com.raquo" %%% "domtypes" % "0.3" Currently it produces these compile-errors:
|
033142a
to
50dd451
Compare
propCodec: Codec[V, DomPropV] | ||
): AttributeBuilder[V] = | ||
new AttributeBuilder(attrKey, CodecBuilder.encodeAttribute(attrCodec)) | ||
//or: new PropertyBuilder(propKey, CodecBuilder.encodeProperty(propCodec)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, we can decide whether we want to represent the reflected attributes as attributes or properties. See https://github.com/raquo/scala-dom-types#reflected-attributes
|
||
/** Snabbdom Key Attribute */ | ||
trait SnabbdomKeyAttributes { | ||
//TODO are these necessary? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this?
//The BooleanAsAttrPresenceCodec does not play well with snabbdom. it | ||
//encodes true as "" and false as null, whereas snabbdom needs true/false | ||
//of type boolean (not string) for toggling the presence of the attribute. | ||
case _: BooleanAsAttrPresenceCodec.type => (v: V) => v.asInstanceOf[Boolean] //TODO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is still TODO! we just need to ignore the BooleanAsPresenceCodec.
Check attributes in snabbdom, accepting and properties in snabbdom, accepting So i think, |
59cb269
to
d7c39cf
Compare
case _ => codec.encode _ | ||
// snabbdom needs true/false of type boolean (not string) for toggling the presence of the attribute. | ||
def encodeAttribute[V](codec: Codec[V, String]): V => Attr.Value = { | ||
case b: Boolean => b |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not correct. We would interpret every boolean value as a boolean attribute
. But only attributes with a BooleanAsAttrPresenceCodec
codec should be rendered like this.
Forr example contenteditable is not a boolean attribute, but an attribute with an enumerated value (true|false
).
Edit: I have added some test for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I missed that. Thanks for adding the test.
I haven't looked at everything in full detail yet, but this looks really good so far and I trust you guys to know what you're doing! 👍 |
|
||
lazy val `for`: RA[String, String] = forId | ||
@deprecated("Use forId instead", "0.11.0") | ||
lazy val `for` = forId |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why should we deprecate this? Maybe scala-dom-types could include it and also `class`
? It already includes `type`
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be fine with me, I already opened a PR for class
, but maybe we can even have both? :)
lazy val inputNumber = onInputNumber | ||
|
||
@deprecated("Use onInputChecked instead", "0.11.0") | ||
lazy val inputChecked = onInputChecked |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea to add these for backwards compatibility! I think we should add a few other commonly used attrs/props, such as: click
, keydown
,...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right! i guess input
and change
are also very popular, but there meaning definitely changed because of the lack of InputEvent
(same as for createInputEventHandler()
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... yes. I don't think we can alias input
and change
because of the different meaning. Probably better to get a compilation error in that case.
import org.scalajs.dom.{ClipboardEvent, DragEvent, KeyboardEvent, MouseEvent} | ||
import outwatch.dom.helpers.InputEvent | ||
|
||
import scala.language.higherKinds |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These imports are not necessary, as we have all language features enabled via a compiler flag
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's correct. Intellij is was not smart enough to realise that :)
Added some attribute aliases for backwards compatibility. This allows for example the What other attributes/tags should we alias with deprecation warnings? |
|
||
trait AttributesCompat { | ||
lazy val `class` = className |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which attributes should be deprecated? I kind of like the idea to mainly rely on scala-dom-types defined names, but I guess we can make some exceptions: Do we want to keep for
and class
or should we deprecate them? I think it should be either both or none. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
decided to keep for
and class
. the rest is deprecated.
ca3f327
to
6d7833d
Compare
@raquo Thank you so much for helping in integrating scala-dom-types into outwatch. Great work! |
The next step would be to advertise |
We could use https://github.com/raquo/scala-dom-types for building vnode and just hook our builders. This way we could get rid of all the html definitions in the code.
This is not entirely done. As we currently cannot mixin Tags, Attributes and Events together into one object like we do with
dom
. After disucssing with the maintainer, this might get fixed. But we need to consider that we will anyhow never be able to mixin Styles and Properties into it, because they will conflict with the Attributes.What do you think?