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

Allow setting component properties through JS properties, not only setAttribute() #3469

Closed
nmsmith opened this issue Mar 17, 2018 · 8 comments

Comments

@nmsmith
Copy link

nmsmith commented Mar 17, 2018

The standard setAttribute() function on DOM elements is defined to accept a string for both the attribute name and value. A-Frame breaks this standard by allowing the value passed in to be an arbitrary object.

This could be brushed away as inconsequential, except Elm's fantastic HTML library and virtual DOM expects attributes to be strings, and thus offers no way to take advantage of A-Frame's more efficient object-passing approach.

Browsers provide another interface to set attributes: through JS properties. Mutating A-Frame components this way would change the interface from:
entity.setAttribute('position', {x: 1, y: 2, z: 3})

to:
entity.position = {x: 1, y: 2, z: 3}

Apart from it being more concise and maintaining consistency with regular HTML, adding such an interface would enable object assignment to be used in Elm, since Elm provides a means to specify DOM element properties.

This interface to set properties might also provide the opportunity to alleviate some of the overhead associated with the current setAttribute().

@dmarcos
Copy link
Member

dmarcos commented Mar 17, 2018

Thanks for filing. For position, rotation and scale you can modify the object3D directly:

 entityEl.object3D.position.x = 5;

@ngokevin
Copy link
Member

You can serialize to string with like component.stringify or AFRAME.utils.styleParser.stringify

@nmsmith
Copy link
Author

nmsmith commented Mar 18, 2018

Thanks for the responses. I think I need to clarify further: Elm is its own programming language, and you can't write JavaScript as part of an Elm program. For manipulating web pages, Elm provides bindings to the DOM API. Since A-Frame is supposed to be HTML-based, we should be able to use it solely through the DOM API. And we can, if we use the standard string-based setAttribute() function that is part of the API. Apart from this being clunky to use programmatically, stringifying every value and having A-Frame immediately parse it again adds unnecessary overhead to every call. This is why A-Frame provides other overloads of setAttribute().

However, the overloads defined by A-Frame are not part of the DOM API: Elm doesn't know these overloads exist, and provides no way to call them. A different approach to setting attributes that is part of the API is DOM element properties. DOM element properties are not defined to be solely strings, and so we are allowed to assign arbitrary objects. Elm consequently provides a mechanism to set both standard properties and custom ("expando") properties.

In the case of the example given above, object3D is an expando property:
entityEl.object3D.position.x = 5;

Unfortunately this is a direct exposure of a Three.js object, and thus I can't create my own "object3D" or my own "position" to assign as a property without using Three.js constructors. I can only mutate the objects that currently exist.

However, I can already assign my own position using the attribute-based interface:
entity.setAttribute('position', {x: 1, y: 2, z: 3})

The equivalent functionality I'm proposing is to use standard DOM API properties to achieve this direct value assignment without breaking the HTML/DOM-based abstraction that A-Frame champions:
entity.position = {x: 1, y: 2, z: 3}

...where position is an expando property backed by a setter that redirects the assigned object to the same place setAttribute() does.

If the objects assigned via this property interface remain Plain Old Data as attributes currently are, then this solution will work really well with Elm, and of course JS too.

@ngokevin
Copy link
Member

ngokevin commented Apr 4, 2018

Thanks for filing. Unfortunately while this may suck, we can't provide that sort of API. If that means Elm won't work well with A-Frame, I think that's how it is. For the purposes of building VR applications, Elm is not strictly necessary, and we won't be bending A-Frame to fit Elm or existing Web tools built for 2D Web. Will be closing, but happy to discuss further!

@ngokevin ngokevin closed this as completed Apr 4, 2018
@nmsmith
Copy link
Author

nmsmith commented Apr 4, 2018 via email

@dkmg24
Copy link

dkmg24 commented Sep 24, 2018

@ngokevin I'm also interested in why this wouldn't be possible.

...we won't be bending A-Frame to fit Elm or existing Web tools built for 2D Web.

Elm isn't built for just the 2D web; there's even a WebGL package for Elm.

Elm's killer feature is its declarative app architecture which lets you map Model -> View without the usual mess of glue code. Elm's declarative app architecture paired with A-Frame's rock-solid VR and WebGL abstractions would be insanely cool. The cherry on top is that A-Frame is already declarative and DOM-based, which means Elm is tantalizingly close to working with A-Frame out of the box (and kind of did up to 412d162).

Their names even pun together ;) It would be an absolute tragedy if Elm and A-Frame couldn't play well together.

PS: Thanks for creating A-Frame. It's awesome by itself!

@tilmans
Copy link

tilmans commented Sep 24, 2018

@ngokevin I also want to support this, Elm provides a wonderful way for building complex, interactive A-Frame scenes and it feels extremely natural to use the combination of the two. It would be great if this would work again.

@ngokevin
Copy link
Member

ngokevin commented Sep 24, 2018

We're not going to introduce, support, and maintain multiple redundant APIs/codepaths to do the same thing. The example given so far was for position which is a simple case. There are hundreds of components that can each have dozens of properties. It's messy to attach a ton of random nested properties onto the element namespace. And setting component properties have massive side effects that should not be represented as a simple JS property change.

Frameworks and toy integrations are cool, but I rarely see these apps go beyond the constraints of placing basic shapes and models.

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

5 participants