为什么我的简单 Ember.js Handlebars 助手在异步加载数据时不起作用?

发布于 2025-01-01 08:21:14 字数 3070 浏览 0 评论 0原文

我有一个简单的 Handlebars 助手,它可以简单地格式化货币值。当我使用静态数据进行测试时,该帮助程序可以正常工作,但当我异步加载数据时,该帮助程序则无法正常工作。换句话说,{{totalBillable}} 将输出预期金额,但 {{money TotalBillable}} 将输出零。但仅当通过 ajax 调用加载数据时。我到底做错了什么?

我尝试尽可能地减少代码,并在这里创建了一个 jsfiddle: http://jsfiddle.net/Gjunkie/wsZXN/2/

这是一个 Ember 应用程序:

App = Ember.Application.create({});

这是把手助手:

Handlebars.registerHelper("money", function(path) {
  var value = Ember.getPath(this, path);
  return parseFloat(value).toFixed(2);
});

模型:

App.ContractModel = Ember.Object.extend({});

应用程序控制器:

App.appController = Ember.Object.create({
    proprietor: null,
});

合同控制器(管理合同数组):

App.contractsController = Ember.ArrayController.create({
    content: [],

    totalBillable: function() {
        var arr = this.get("content");
        return arr.reduce(function(v, el){
            return v + el.get("hourlyRate");
        }, 0);
    }.property("content"),

当所有者发生变化时,通过 ajax 请求获取新的合同数据。异步获取数据时,车把助手不起作用。

    proprietorChanged: function() {
        var prop = App.appController.get("proprietor");
        if (prop) {
            $.ajax({
                type: "POST",
                url: '/echo/json/',
                data: {
                    json: "[{\"hourlyRate\":45.0000}]",
                    delay: 1
                },
                success: function(data) {
                    data = data.map(function(item) {
                        return App.ContractModel.create(item);
                    });
                    App.contractsController.set("content", data);
                }
            });
        }
        else {
            this.set("content", []);
        }
    }.observes("App.appController.proprietor")
});

如果我改用这个版本,那么 Handlebars 助手将按预期工作:

    proprietorChanged: function() {
        var prop = App.appController.get("proprietor");
        if (prop) {
            var data = [{
                "hourlyRate": 45.0000}];
            data = data.map(function(item) {
                return App.ContractModel.create(item);
            });
            App.contractsController.set("content", data);
        }
        else {
            this.set("content", []);
        }
    }.observes("App.appController.proprietor")

查看:

App.OverviewTabView = Ember.TabPaneView.extend({
    totalBillableBinding: "App.contractsController.totalBillable"
});

通过设置所有者模板来开始工作

App.appController.set("proprietor", {
    ID: 1,
    name: "Acme"
});

<script type="text/x-handlebars">
    {{#view App.OverviewView viewName="overview"}}
        <div class="summary">
           Total Billable: {{totalBillable}}<br/>
           Total Billable: {{money totalBillable}}<br/>
        </div>
    {{/view}}
</script>

I have a simple Handlebars helper which simply formats a money value. The helper works property when I test with static data, but not when I load data asynchronously. In other words, {{totalBillable}} will output the expected amount, but {{money totalBillable}} will output zero. But only when the data is loaded via an ajax call. What the heck am I doing wrong?

I've tried to pare the code down as much as possible, and also created a jsfiddle here:
http://jsfiddle.net/Gjunkie/wsZXN/2/

This is an Ember application:

App = Ember.Application.create({});

Here's the handlebars helper:

Handlebars.registerHelper("money", function(path) {
  var value = Ember.getPath(this, path);
  return parseFloat(value).toFixed(2);
});

Model:

App.ContractModel = Ember.Object.extend({});

App Controller:

App.appController = Ember.Object.create({
    proprietor: null,
});

Contracts Controller (manages an array of contracts):

App.contractsController = Ember.ArrayController.create({
    content: [],

    totalBillable: function() {
        var arr = this.get("content");
        return arr.reduce(function(v, el){
            return v + el.get("hourlyRate");
        }, 0);
    }.property("content"),

When the proprietor changes, get new contract data with an ajax request. When getting data asynchronously, the handlebars helper does not work.

    proprietorChanged: function() {
        var prop = App.appController.get("proprietor");
        if (prop) {
            $.ajax({
                type: "POST",
                url: '/echo/json/',
                data: {
                    json: "[{\"hourlyRate\":45.0000}]",
                    delay: 1
                },
                success: function(data) {
                    data = data.map(function(item) {
                        return App.ContractModel.create(item);
                    });
                    App.contractsController.set("content", data);
                }
            });
        }
        else {
            this.set("content", []);
        }
    }.observes("App.appController.proprietor")
});

If I use this version instead, then the Handlebars helper works as expected:

    proprietorChanged: function() {
        var prop = App.appController.get("proprietor");
        if (prop) {
            var data = [{
                "hourlyRate": 45.0000}];
            data = data.map(function(item) {
                return App.ContractModel.create(item);
            });
            App.contractsController.set("content", data);
        }
        else {
            this.set("content", []);
        }
    }.observes("App.appController.proprietor")

View:

App.OverviewTabView = Ember.TabPaneView.extend({
    totalBillableBinding: "App.contractsController.totalBillable"
});

Kick things off by setting a proprietor

App.appController.set("proprietor", {
    ID: 1,
    name: "Acme"
});

Template:

<script type="text/x-handlebars">
    {{#view App.OverviewView viewName="overview"}}
        <div class="summary">
           Total Billable: {{totalBillable}}<br/>
           Total Billable: {{money totalBillable}}<br/>
        </div>
    {{/view}}
</script>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

陌伤浅笑 2025-01-08 08:21:14

使用助手时,handlebars 不会在您的助手调用周围发出变形标签。这样,模板的这一部分就不会重新渲染,因为没有绑定

来手动绑定要重新渲染的模板的一部分,您可以使用 bind 帮助器:

<script type="text/x-handlebars">
  {{#view App.OverviewView viewName="overview"}}
    <div class="summary">
       Total Billable: {{totalBillable}}<br/>
       Total Billable: {{#bind totalBillable}}{{money this}}{{/bind}}<br/>
    </div>
  {{/view}}
</script>

when using a helper, handlebars does not emit metamorph tags around your helper call. this way, this part of the template is not re-rendered because there is no binding

to manually bind part of a template to be re-rendered, you can use the bind helper:

<script type="text/x-handlebars">
  {{#view App.OverviewView viewName="overview"}}
    <div class="summary">
       Total Billable: {{totalBillable}}<br/>
       Total Billable: {{#bind totalBillable}}{{money this}}{{/bind}}<br/>
    </div>
  {{/view}}
</script>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文