0

我对流星相当陌生。

我有一个模板帮助函数,它需要处理我从服务器端发布的数据。当页面加载时,下面 profile 的值为undefined。但在那之后,当我从浏览器的控制台执行相同的代码片段时,它工作得很好。据我了解,模板助手是在数据发布之前执行的。如何等到数据发布后再运行 UI 助手?

这是相关代码。


辅助函数

Template.header.helpers({  
  me: function() {
    var user = Meteor.users.findOne(Meteor.userId());
    if (user) {
      return Profiles.findOne({
        spid: user.profile.spid
     });
    }

    return null;
  }
});

HTML 模板

<template name="header">
  <header class="ui fixed inverted menu">
    {{> thumb user=me}}
  </header>
</template>

缩略图模板

<template name="thumb">
  {{#with user}}
  <div class="thumb">
    <div class="text" style="background-color:{{color}}">
      {{initials name}}
    </div>
    <div class="pic" style="background-image:url('{{pic}}')"></div>
  </div>
  {{/with}}
</template>

出版物

Meteor.publish('profiles', function() {
  return Profiles.all();
});

Meteor.publish('departments', function() {
  return Departments.all();
});

Meteor.publish('requestServiceIds', function() {
  return Requests.getServiceIds();
});

Meteor.publish('relevantServices', function() {
  return Services.getRelevant(this.userId, 5);
});

路由器

Router.configure({
  layoutTemplate: 'main',
  waitOn: function() {
    Deps.autorun(function() {
      Meteor.subscribe('profiles', Partitioner.group());
      Meteor.subscribe('departments', Partitioner.group());
    });
  }
});

Router.onBeforeAction(function() {
  if (this.route.getName() === 'not-authorized') return this.next();

  if (!Meteor.userId() || !Cookie.get('TKN')) {
    this.render('login');
  } else {
    this.next();
  }
});

Router.route('/', {
  name: 'home',
  waitOn: function() {
    Deps.autorun(function() {
      Meteor.subscribe('requestServiceIds', Partitioner.group());
      Meteor.subscribe('relevantServices', Partitioner.group());
    });
  }
});

---

更新 1

我稍微更新了路由器。但这似乎没有任何区别。

Router.configure({
  layoutTemplate: 'main',
  waitOn: function() {
    // Deps.autorun(function() {
    //   Meteor.subscribe('profiles', Partitioner.group());
    //   Meteor.subscribe('departments', Partitioner.group());
    // });

    return [
      Meteor.subscribe('profiles', Partitioner.group()),
      Meteor.subscribe('departments', Partitioner.group())
    ];
  }
});

Router.route('/', {
  name: 'home',
  waitOn: function() {
    // Deps.autorun(function() {
    //   Meteor.subscribe('requestServiceIds', Partitioner.group());
    //   Meteor.subscribe('relevantServices', Partitioner.group());
    // });

    return [
      Meteor.subscribe('requestServiceIds', Partitioner.group()),
      Meteor.subscribe('relevantServices', Partitioner.group())
    ];
  }
});
4

1 回答 1

0

创建一个愚蠢的加载模板,例如这个(使用字体真棒):

<template name="loading">
    <div class="loading">
        <i class="fa fa-circle-o-notch fa-4x fa-spin"></i>
    </div>
</template>

并尝试用以下内容替换您的Router.configure()部分:

Router.configure({
  layoutTemplate: 'main',
  action: function() {
        if(this.isReady()) { this.render(); } else {this.render("loading");}
    },
    isReady: function() {
        var subs = [
            Meteor.subscribe('profiles', Partitioner.group());
            Meteor.subscribe('departments', Partitioner.group());
        ];
        var ready = true;
        _.each(subs, function(sub) {
            if(!sub.ready())
            ready = false;
        });
        return ready;
    },

    data: function() {
        return {
            params: this.params || {},
            profiles: Profiles.find(),
            departments: Departments.find()
        };
    }
  }
});

我想这可以使用 来实现waitOn,但由于你的方法不起作用,我给你一个我每天都用的有效食谱。代码灵感来自于流星厨房生成的代码。


要回答您的意见:

关于Action没有被触发,可能是因为我们试图把Router.configure. 我不是那样做的,这里有一些关于我如何实现它的细节。

首先,我为 router.js 文件中的每个路由设置了一个控制器(我也有我的Router.configure()功能。它看起来像这样:

Router.map(function () {
    this.route("login", {path: "/login", controller: "LoginController"});
    // other routes
}

接下来,我创建一个控制器,将其存储在与客户端视图模板相同的文件夹中。它看起来像这样:

this.LoginController = RouteController.extend({
    template: "Login",


    yieldTemplates: {
        /*YIELD_TEMPLATES*/
    },

    onBeforeAction: function() {
        /*BEFORE_FUNCTION*/
        this.next();
    },

    action: function() {
        if(this.isReady()) { this.render(); } else { this.render("loading"); }
        /*ACTION_FUNCTION*/
    },

    isReady: function() {


        var subs = [
        ];
        var ready = true;
        _.each(subs, function(sub) {
            if(!sub.ready())
                ready = false;
        });
        return ready;
    },

    data: function() {


        return {
            params: this.params || {}
        };
        /*DATA_FUNCTION*/
    },

    onAfterAction: function() {
    }
});

因此action,当我使用控制器扩展路由时,此功能起作用。也许它会解决你的问题。

为了完整起见,这是我的Router.configure()样子:

Router.configure({
  templateNameConverter: "upperCamelCase",
  routeControllerNameConverter: "upperCamelCase",
  layoutTemplate: "layout",
  notFoundTemplate: "notFound",
  loadingTemplate: "loading",
 //I removed the rest because it is useless.
});
于 2015-07-31T13:23:14.900 回答