The view element and it's content are separate in HTML


#1

Hi, I create a component.

    <script type="text/x-handlebars" data-template-name="components/tree-grid-row">
    <tr {{bind-attr class="isShown:grid-row:grid-row-hide isSelected:grid-row-selected"}}
        {{action "select" on="click"}}>
        <td {{bind-attr class=":grid-cell"}}>
            <div {{bind-attr class=":expansion-cell" style="left_margin"}}>
                <div {{bind-attr class="hasChildren:show-tree-operation:hide-tree-operation"}}>
                    {{tree-grid-expand-icon isExpanded=isExpanded
                        action="toggleExpansion"}}
                </div>
                <div {{bind-attr class=":expansion-cell-content"}}>
                    {{row.name}}
                </div>
            </div>
        </td>
        <td {{bind-attr class=":grid-cell"}}>{{row.detail}}</td>
    </tr>
</script>

And use it here

            {{#each row in rows}}
   {{tree-grid-row row=row action="toggleRowChildren"}}
{{/each}}

And I found the resulting HTML is problematic.

    <div>
   <div id="ember386" class="ember-view"> </div>
   <div id="ember395" class="ember-view"> </div>
   <div id="ember398" class="ember-view"> </div>
   <table class="grid-table">
       <thead class="grid-header">
       <tbody>
         <script id="metamorph-8-start" type="text/x-placeholder">
         <script id="metamorph-5-start" type="text/x-placeholder">
         <tr class="grid-row" data-ember-action="4" data-bindattr-3="3">
         <script id="metamorph-5-end" type="text/x-placeholder">
         <script id="metamorph-6-start" type="text/x-placeholder">
         <tr class="grid-row-hide" data-ember-action="13" data-bindattr-12="12">
         <script id="metamorph-6-end" type="text/x-placeholder">
         <script id="metamorph-7-start" type="text/x-placeholder">
         <tr class="grid-row-hide" data-ember-action="22" data-bindattr-21="21">
         <script id="metamorph-7-end" type="text/x-placeholder">
         <script id="metamorph-8-end" type="text/x-placeholder">
       </tbody>
    </table>
</div>

Three view elements are created (“ember386”, “ember3965”, “ember398”). But they’re not inline in the element tbody and the element such as <tr class="grid-row" data-ember-action="4" data-bindattr-3="3"> isn’t inline in the view element either. This leads to a problem of updating the view. I’ve encountered a problem when I update the property “isShown”. The property is updated correctly in the component’s Javascript code, but it’s not reflected in the tempalte. When I debugged, I found that ember tries to look up the element like “data-bindattr-12” from the view “ember395” and nothing is found. So the view isn’t actually updated.

It seems to me that the HTML should look like:

<div>
   <table class="grid-table">
       <thead class="grid-header">
       <tbody>
         <script id="metamorph-8-start" type="text/x-placeholder">
         <script id="metamorph-5-start" type="text/x-placeholder">
         <div id="ember386" class="ember-view">
             <tr class="grid-row" data-ember-action="4" data-bindattr-3="3">
         </div>
         <script id="metamorph-5-end" type="text/x-placeholder">
         <script id="metamorph-6-start" type="text/x-placeholder">
         <div id="ember395" class="ember-view">
         <tr class="grid-row-hide" data-ember-action="13" data-bindattr-12="12">
         </div>             
         <script id="metamorph-6-end" type="text/x-placeholder">
         <script id="metamorph-7-start" type="text/x-placeholder">
         <div id="ember398" class="ember-view">
             <tr class="grid-row-hide" data-ember-action="22" data-bindattr-21="21">
         </div>
         <script id="metamorph-7-end" type="text/x-placeholder">
         <script id="metamorph-8-end" type="text/x-placeholder">
       </tbody>
    </table>
</div>

At least, when I try to show other component, the view element and its contents are all inline.

Does anybody encounter such problems? And how to solve it?

A complete code is at https://github.com/kceiw/treegrid-emberjs All templates are in index.html and components are in js/components


#2

I think the HTML is actually being output as per your last example but the browser is reorganising it because it’s invalid HTML.

Have you tried setting the element directly in the component? Eg:

DemoApp.TreeGridRowComponent = Ember.Component.extend({
    tagName: 'tr',
    classNameBindings: ['isShown:grid-row:grid-row-hide', 'isSelected:grid-row-selected'],

    actions: {
        click: function () {
            //window.alert("select row.");
        }
    }

    ...
});
<script type="text/x-handlebars" data-template-name="components/tree-grid-row">
    <td {{bind-attr class=":grid-cell"}}>
        <div {{bind-attr class=":expansion-cell" style="left_margin"}}>
            <div {{bind-attr class="hasChildren:show-tree-operation:hide-tree-operation"}}>
                {{tree-grid-expand-icon isExpanded=isExpanded
                    action="toggleExpansion"}}
            </div>
            <div {{bind-attr class=":expansion-cell-content"}}>
                {{row.name}}
            </div>
        </div>
    </td>
    <td {{bind-attr class=":grid-cell"}}>{{row.detail}}</td>
</script>

That should avoid the extra wrapping divs.


#3

Thank you. That woks. Does it mean that a view/compoenent is always in a

if tagName is not specified? I’m surprised that browser will re-organize the elements.

#4

Yes, if it’s not specified then the template contents will always be wrapped in a div.