无法让jqueryui选项卡在Ember视图中正常工作

时间:2013-06-17 15:14:07

标签: jquery-ui ember.js jquery-ui-tabs

我正在尝试在Ember.JS中运行一个小原型,以便完全重写Web应用程序的UI作为针对WebAPI运行的Ember应用程序,但是我已经设法让Ember运行正常,我无法让jqueryui正确初始化标签。

如果在视图中我放置了要创建的选项卡的静态数据,似乎工作正常,但是如果我使用动态数据则它不起作用。

我有一个Ember视图模板

<script type="text/x-handlebars" id="index">
    <div id="tabs" class="ui-tabs">
        <ul>
            {{#each model}}
            <li>
                <span class="ui-icon ui-icon-person"></span>
                <a {{bindAttr href="route"}} {{bindAttr title="tabTitle"}}><span>{{title}}</span></a>
            </li>
            {{/each}}
        </ul>

        {{#each model}}
        <div {{bindAttr id="tabTitle"}}>
            <p>
                Retrieving Data - {{title}}
            </p>
        </div>
        {{/each}}
    </div>
</script>

和视图

App.IndexView = Ember.View.extend({
    templateName: 'index',

    didInsertElement: function () {
        var tabs = $("#tabs").tabs();
    }
});

和模型

App.Section = DS.Model.extend({
    name: DS.attr('string'),
    title: DS.attr('string'),
    tabTitle: function () {
        return 'tab-' + this.get('name');
    }.property("name"),
    route: function () {
        return '#' + this.get('tabTitle');
    }.property("tabTitle")
});

App.Section.FIXTURES = [
    {
        id: 1,
        name: 'home',
        title: 'Home'
    },
    {
        id: 2,
        name: 'users',
        title: 'Users'
    }
];

它似乎正确生成HTML(从检查Firebug),但这不起作用,就好像我用

替换模板
<script type="text/x-handlebars" id="index">
    <div id="tabs" class="ui-tabs">
        <ul>
            <li>
                <span class="ui-icon ui-icon-person"></span>
                <a href="#tab-home" title="tab-home"><span>Home</span></a>
            </li>
            <li>
                <span class="ui-icon ui-icon-person"></span>
                <a href="#tab-users" title="tab-users"><span>Users</span></a>
            </li>
        </ul>

        <div id="tab-home">
            <p>
                Retrieving Data - Home
            </p>
        </div>
        <div id="tab-users">
            <p>
                Retrieving Data - Users
            </p>
        </div>
    </div>
</script>

效果很好。

我假设在初始化选项卡时没有完全呈现DOM,但是我能找到的所有东西都说didInsertElement就是这样做的地方,我有时间深入挖掘爱好。

我很感激任何想法。

编辑:我通过以下方式成功地完成了这项工作:

App.IndexView = Ember.View.extend({
    templateName: 'index',

    didInsertElement: function () {
        Ember.run.next(this, function () {
            if (this.$('#tab-users').length > 0) {
                var tabs = $('#tabs').tabs();
            } else {
                Ember.run.next(this.didInsertElement);
            }
        });
    },
});

这个问题是1)它需要我知道将要写入视图的最后一个元素被调用(显然动态数据我不一定知道),所以我可以继续检查它,2)这种技术的低效率让我想要尖叫!

此外,在渲染完成后,我们会得到一个很好的旧的FoUC(Flash of Unstyled Content),但在我们获得JQueryUI之前,它们才能正确地设置样式。

感激地收到任何建议。

1 个答案:

答案 0 :(得分:0)

它仍然不好......但这至少可行,并且效率相当高......

Ember.js - Using a Handlebars helper to detect that a subview has rendered我发现了如何编写触发器,并且由于运行循环似乎工作的方式,在页面的最后一个循环中插入触发器会导致它被调用n次,但仅循环完成后,快速状态检查“hasBeenTriggered”确保您只执行一次delgate函数。

我的代码现在看起来像这样:

<script type="text/x-handlebars" id="index">
    <div id="tabs" class="ui-tabs">
        <ul>
            {{#each model}}
            <li>
                <span class="ui-icon ui-icon-person"></span>
                <a {{bindAttr href="route"}} {{bindAttr title="tabTitle"}}><span>{{title}}</span></a>
            </li>
            {{/each}}
        </ul>

        {{#each model}}
        <div {{bindAttr id="tabTitle"}}>
            <p>
                Retrieving Data - {{title}}
            </p>
        </div>
        {{trigger "triggered"}}
        {{/each}}
    </div>
</script>

带触发器

Ember.Handlebars.registerHelper('trigger', function (evtName, options) {
    options = arguments[arguments.length - 1];
    var hash = options.hash,
        view = options.data.view,
        target;

    view = view.get('concreteView');

    if (hash.target) {
        target = Ember.Handlebars.get(this, hash.target, options);
    } else {
        target = view;
    }

    Ember.run.next(function () {
        target.trigger(evtName);
    });
});

并查看

App.IndexView = Ember.View.extend({
    templateName: 'index',

    hasBeenTriggered: false,

    triggered: function () {
        if (!this.get("hasBeenTriggered")) {
            var tabs = $('#tabs').tabs();
            this.set("hasBeenTriggered", true);
        }
    }
});

我很想知道是否有更好的方法可以做到这一点,因为这仍然无法解决FOUC问题(再次可以通过更多JS黑客攻击)...... :(