stevenrskelton / sortable-table

Polymer Web Component that generates a sortable <table> from inlined or AJAX JSON, JSON5, and arrays.
https://stevenrskelton.github.io/sortable-table/
MIT License
196 stars 37 forks source link

Adding templates dinamycally #21

Open roalva1 opened 9 years ago

roalva1 commented 9 years ago

Hello,

I was wondering if we can add templates dynamically, i.e. to create a select with values , put it in a template and add it to the sortable table. This is my code:

cellTemplate = "newCellTemplate"; var el = document.createElement("template"); el.id = cellTemplate; var td = document.createElement("td"); el.appendChild(td); var select = document.createElement("select"); select.setAttribute("type", "text"); td.appendChild(select); for (var i = 0; i < this.categoricalValues.length; i++) { var option = document.createElement("option"); option.value = this.categoricalValues[i]; var text = document.createTextNode(this.categoricalValues[i]); option.appendChild(text); select.appendChild(option); } this.$.sortable_table.shadowRoot.appendChild(el); //this.$.sortable_table.appendChild(el);

The html element is well created and you can see the element in DOM, but it does not appear what was expected. If I put the template directly, not programatically in the code it works good, so it is not the way the template is created:

Regards, thank you

stevenrskelton commented 9 years ago

I know what you are talking about, and I think the problem is modifying ShadowDOM from the outside is likely the wrong approach.

My guess is the best way to do this is to add it to the light DOM (nodes between the <sortable-table> tags) and let Polymer pull it in. It doesn't do this automatically of course, but it's something I'll look into implementing.

I wonder if it's as simple as adding a <content select="template">. I've been busy lately but am looking to put much more work into this real soon.

roalva1 commented 9 years ago

First, I tried to put it in the light DOM this.$.sortable_table.appendChild(el); but the result was the same.

Regards

stevenrskelton commented 9 years ago

I was playing around with this, and when creating a template programmatically, be sure to append elements to template.content.

I got your example to work, one thing to be careful of is to not reference a template until after it has been added to sortable-table. sortable-table won't try to relink broken template references, but it does allow you to change them after initialization.

<sortable-table id="example" class="default">
[
        { "fruit":"apple",      "alice": 4, "bill": 10, "casey": 2 },
        { "fruit":"banana",     "alice": 0, "bill": 4,  "casey": 0 },
        { "fruit":"grape",      "alice": 2, "bill": 3,  "casey": 5 },
        { "fruit":"pear",       "alice": 4, "bill": 2,  "casey": 8 },
        { "fruit":"strawberry", "alice": 0, "bill": 14, "casey": 0 }
]
</sortable-table>

<input type="button" onclick="copyTemplate()" value="Set New Template">

<script>

function copyTemplate(){
    this.categoricalValues = ["cv1","cv2","cv3"];
    var cellTemplate = "newCellTemplate";
    var el = document.createElement('template');
    el.id = cellTemplate;
    var td = document.createElement("td");
    el.content.appendChild(td);
    var select = document.createElement("select");
    select.setAttribute("type", "text");
    td.appendChild(select);
    for (var i = 0; i < this.categoricalValues.length; i++) {
        var option = document.createElement("option");
        option.value = this.categoricalValues[i];
        var text = document.createTextNode(this.categoricalValues[i]);
        option.appendChild(text);
        select.appendChild(option);
    }
    var sortableTable = document.getElementById('example');
    sortableTable.appendChild(el);
    sortableTable.columns[2].cellTemplate = el.id;
}
</script>

There are probably better ways to achieve this using args (but I'm aware people seem to run into crazy use-cases so :four_leaf_clover: )

<sortable-table id="example" class="default">
    <sortable-column>Fruit</sortable-column>
    <sortable-column cellTemplate="newCellTemplate">Alice</sortable-column>
    <sortable-column>Bill</sortable-column>
    <sortable-column>Casey</sortable-column>

    <template id="newCellTemplate">
        <td>
            <select type="text">
                <template repeat="{{cv in args.categoricalValues}}">
                    <option value="{{cv}}">{{cv}}</option>
                </template>
            </select>
        </td>
    </template>
    [
        ['apple', 4, 10, 2 ],
        ['banana', 0, 4, 0 ],
        ['grape', 2, 3, 5 ],
        ['pear', 4, 2, 8 ],
        ['strawberry', 0, 14, 0 ],
        ['apple', 5, 6, 4 ],
        ['banana', 3, 9, 2 ],
        ['grape', 8, 3, 0 ],
        ['pear', 0, 7, 4 ],
        ['strawberry', 4, 5, 2 ]
    ]
</sortable-table>
<script>
window.addEventListener('polymer-ready', function(){
    document.getElementById('example').args = {
        categoricalValues: ["cv1","cv2","cv3"]
    };
});
</script>