bakerac4 / glimmer-native

77 stars 5 forks source link

Render Component needs wrapper #25

Open bakerac4 opened 5 years ago

bakerac4 commented 5 years ago

When rendering a component, currently we need a wrapper template to be rendered which contains the component we actually want to render.

It seems that without the wrapper template, a new class instance of the actual component we want to render is not created. Therefore all functions and properties are undefined i.e {{this.onClick}} is undefined.

Here is an example of a wrapper template in use

This poses a larger issue however when working with ListViews. Currently you need to pass in a wrapper template, which means you basically need to pass in any arguments as a pass through to your actual component you would like to render.

For example, Right now to use a ListView you do this

    <RadListView
        row="7"
        colSpan="2"
        loadOnDemandBufferSize="16"
        loadOnDemandMode={{this.loadMode}}
        selectionBehavior="Press"
        @items={{this.posts}}
        {{on "loadMoreDataRequested" this.loadMore}}
        {{on "loaded" this.listViewLoaded}}
        {{on "itemSelected" this.viewPost}}
        {{set "listViewLayout" this.layout true}}
    >
        <Template @src={{this.listViewTemplate}} @itemClicked={{this.itemClicked}}/>
    </RadListView>

where listViewTemplateSource would be something like

    listViewTemplate = `<HomeFeedListItem
                        @item={{this.item}}
                        @itemClicked={{this.itemClicked}} />`;

and then Glimmer Native takes the value passed into the template for this.itemClicked and send sit in to the listViewTemplate when we render.

I'd like to find a way to remove the wrapper component but still have a new instance of the class component be created.

lifeart commented 5 years ago

can ast transform help with it?

lifeart commented 5 years ago

basically, it may be an component helper?

    listViewTemplate = `<HomeFeedListItem
                        @item={{this.item}}
                        @itemClicked={{this.itemClicked}} />`;

with ember can be rewritted as

{{#let (component HomeFeedListItem item=this.item itemClicked=this.itemClicked as |listViewTemplate |}}
   <SomeComponent @someProperty={{HomeFeedListItem}} />
{{/let}}
lifeart commented 5 years ago

@bakerac4

how about this logic:

<ItemsList template="my-insane-component">
  <template name="my-insane-component">
    <div>
        Hello It's template.
    </div>
  </template>
</ItemsList>

->

{{register-component "my-insane-component" "{\"symbols\":[],\"statements\":[[7,\"h1\",true],[9],[0,\"Hello world\"],[10]],\"hasEval\":false}"}

<ItemsList template="my-insane-component">
</ItemsList>

->

registerComponentHelper([componentName, template]) {
    this.owner.register('component:' + componentName, template);
}

I can write related handlebars transform, if this case looks nice for you

lifeart commented 5 years ago

https://astexplorer.net/#/gist/ddb656974fec413fdfde80c1329645d1/36f976b32b8c37fea517b29155216457e197b8ff

templateCompileFunction should be implemented as

const { precompile } = require('@glimmer/compiler');
const { print } = require('@glimmer/syntax');
function templateCompileFunction(node) {
    return btoa(precompile(print(node)))
}
lifeart commented 5 years ago

I can update AST transform to support glimmer-like syntax

<ItemsList as |template data|>
  <template>
    <div>
                {{data.name}}
        Hello It's template.
    </div>
  </template>
</ItemsList>