渲染动态Enyo中继器

时间:2014-03-12 22:06:51

标签: javascript enyo

我需要为我正在处理的enyo项目创建一个数据表,它最终将显示Ajax调用的结果。 This(从ryanjduffy here公然被盗)似乎是一个很好的起点,但当我尝试从按钮事件(而不是在构造函数中)调用setData()时,我{{3我收到以下错误:

InvalidCharacterError: String contains an invalid character @ http://enyojs.com/enyo-2.1/enyo/source/dom/Control.js:681

我查看了Control.js代码,似乎它尝试创建一个新节点,但this.tag属性设置为null并且事情中断了。

我觉得我错过了一些非常简单的东西,但我还是看不到问题......

有人能告诉我我做错了吗?

谢谢!

编辑1:

显然不需要调用render()。带有render()的here已注释掉。一切看起来都很棒。但是,如果我尝试从Here is the original working version删除render(),则转发器会开始在表格上方创建div而不是tr td在表格内......

编辑2:

基本上,据我所知,表格中的Repeater会在表格渲染后丢失它的父级(或类似的东西)。结果是Repeater将开始在原始表之外呈现其新项目,并且因为没有td的{​​{1}}标记没有意义,它只会呈现table。    我提出的解决方案是给Repeater本身一个div标签,这样它的孩子总能在正确的位置结束。这增加了每次都需要重新创建标题行的挑战,但这并不是什么大不了的事。 version that requires a button click如果有人有兴趣的话。

1 个答案:

答案 0 :(得分:2)

我确定你不再寻找解决方案但是因为我在帖子中提到过,我想我会让你知道我发现了什么。简而言之,我的代码不应该有效,但由于浏览器是宽容的,它确实......有点像。

当代码在创建时运行时,它会呈现如下内容:

<table>
  <tr> <!-- header row --> </tr>
  <div> <!-- repeater tag -->
     <tr> <!-- repeater row --> </tr>
  </div>
</table>

浏览器看着它然后说,&#34;嘿,假! <div>&#34;中没有<table> s然后把它踢出去,但留下<tr> s。

在您的示例中,由于您要延迟行的渲染,Enyo呈现:

<table>
  <tr> <!-- header row --> </tr>
  <div></div>
</table>

浏览器会弹出<div>,然后你会留下一张空桌子。稍后设置数据时,这些行将呈现为div。不幸的是,由于您正在呈现<tr><td>,因此这些内容在表格之外无效,因此您只需获取文字。

我找到了几个解决方案。最简单的方法是将Repeater的tag设置为TBODY,允许在表中使用。稍微复杂一点的解决方案是使DataTable继承自Repeater并将标题行设置为chrome,以便在更新数据时不会删除它们。

Option #2 Fiddle

enyo.kind({
    name:"DataTable",
    tag: "table",
    kind: "Repeater",
    published:{
        map:0,
        data:0
    },
    handlers: {
        onSetupItem: "setupItem"
    },
    components:[
        {name:"row", kind:"DataRow"}
    ],
    create:function() {
        this.inherited(arguments);
        this.mapChanged = this.dataChanged = enyo.bind(this, "refresh");

        this.refresh();
    },
    refresh:function() {
        if(this.map && this.data) {
            this.buildHeader();
            this.setCount(this.data.length);
        }
    },
    buildHeader:function() {
        if(this.$.header) {
            this.$.header.destroyClientControls();
        } else {
            this.createComponent({name:"header", tag:"tr", isChrome: true});
        }

        for(var i=0;i<this.map.length;i++) {
            this.$.header.createComponent({content:this.map[i].header, tag:"th"});
        }

        this.$.header.render();
    },
    setupItem:function(source, event) {
        for(var i=0;i<this.map.length;i++) {
            event.item.$.row.createComponent({content:this.data[event.index][this.map[i].field]});
        }

        event.item.render();

        return true;
    }
});