aurelia / templating-resources

A standard set of behaviors, converters and other resources for use with the Aurelia templating library.
MIT License
59 stars 55 forks source link

Compose element does not support slots or work the same as defining custom element #246

Closed aidenweatherby closed 8 years ago

aidenweatherby commented 8 years ago

I'm submitting a bug report

Please tell us about your environment:

Current behavior: Compose element does not support slots. If I define the custom element and add the html with slot attributes the output is correct. If I use the compose element the html is incorrect. Compose element does not support template attributes defined in custom template.

Expected/desired behavior: I expect using the compose element with a view or view-model attribute should work exactly the same as defining the custom element by itself. So if defining slots in template then compose element should use those slots. If defining attributes on the template node then compose element should use those attributes. https://gist.run/?id=45d1a249dc27892e0cb3b8048f04ff06

jdanyow commented 8 years ago

you'll need to use a custom element to take advantage of advanced templating features like bindable properties, slots, etc.

aidenweatherby commented 8 years ago

That's what I don't understand then because I am using a custom element. If you look at the gist in previous post you can see that it's a custom element and when declaring it in the template as the custom element name it works fine but when declaring it in the compose element it does not work. I would expect that the compose element does exactly what the custom element does.

This gist example is an over simplified version of what I am trying to create but essentially I need to dynamically compose custom elements and keep all functionality as if defining the custom element directly in the template. This is for building dynamic forms from an object which describes the form.

If from what your saying this is not possible then how can I dynamically compose custom elements with slot projection ?

I have worked around this issue by creating my own implementation of the compose element except it feels like a bit of a hack because I have had to reverse engineer some core functionality to do with the compositionEngine and re compiling the custom element template after the compositionEngine has created the controller. Could you please give me some advice on this approach or a better approach if one already exists in Aurelia ? See this gist for an example of previous but with my custom compose element. https://gist.run/?id=ba285c893d7825a4fa69136df95266e3

cheers

jdanyow commented 8 years ago

re: dynamic form- assuming you have a data structure that lists the fields and their types, couldn't you repeat over the fields and use if.bind to display the appropriate control?

The key here is dynamic composition (compose, router-view) work differently than custom elements. This is intentional asfaik. Compose can access the outer scope, custom elements are more encapsulated. http://stackoverflow.com/a/38920425/725866

aidenweatherby commented 8 years ago

The dynamic form is a quite a bit more complicated. It's basically an OIM mapper which is similar to an ORM mapper. So doing a bunch of if.bind would not be suitable because it's too limited. The data structure of the mapping is quite complex where it can map any entity to a UI. So if the entity contains fields and those fields contain entities, arrays of entities, maps of entities, generic entities etc etc.

The mapper supports component types which directly map to a custom element, these component types need the flexibility to be overridden and extended so more component types can be registered etc. Currently the only thing that comes close to supporting this is the compose element but it has the limitations I have mentioned.

The only option I have come up with so far is to do what I am currently doing with my custom compose element as can be seen here https://gist.run/?id=ba285c893d7825a4fa69136df95266e3

Here is an example of the structure and the expected template I want to build.

{
 type:'com.Entity',
 fields:[
  {type:'String', name:'field1'},
  {type:'int[]', name:'amounts'},
  {type:'Map<String,Int>', name:'keyvalues'}
]
}
<entity-field>
  <string-field></string-field>
  <array-field>
    <int-field></int-field>
 </array-field>
 <map-field>
   <mapentry-field >
      <string-field></string-field>
      <int-field></int-field>
   </mapentry-field>
  </map-field>
</entity-field>