流星铁路由器嵌套的路线 [英] meteor iron-router nested routes

查看:73
本文介绍了流星铁路由器嵌套的路线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个具有一对多关系的流星集合:建筑物和空间

在我的建筑物页面上,我想显示与建筑物有关的空间.

现在,我是这样做的:

buildingsRoute.coffee
    BuildingController = RouteController.extend(template: "buildings")
    Router.map ->
      @route "building",
        path: "/buildings/:_id"
        waitOn: ->
          subs.subscribe "allBuildings"
          subs.subscribe "allSpaces"

        data: ->
          building: Buildings.findOne(@params._id)
          spaces: Spaces.find({building_id: @params._id})

building.jade:

template(name="building")
        +with building
            .building
                .page-header.position-relative
                    h1.inline #{name}
                .row
                    .col-xs-12
                       +spacesList

template(name="spacesList")
    .widgets
        .row
            h1 Spaces
            +each spaces
                .col-xs-12.col-sm-6
                    .widget-box.widget-color-purple
                        .widget-header
                            a(href="{{pathFor 'space'}}") #{name}
                        .widget-body
                            p Content here

这是不行的,我想是因为spacesList模板的数据上下文与铁路由器为构建而定义的上下文不同.

我可以用"+ each ../spaces"替换"+ each spaces",但这对我来说似乎不是一个非常通用的解决方案(如果我想在其他情况下使用我的spaceslist模板呢?)

所以我试图像这样在模板助手中定义数据上下文:

Template.spacesList.helpers
  spaces: Spaces.find({building_id: @params._id})

但是我收到错误消息:

Spaces is not defined.

所以我有点困惑.正确实现嵌套路由的流星方法是什么?

谢谢!

空间集合的定义:/models/space.coffee

@Spaces = new Meteor.Collection("spaces",
  schema:
    building_id:
      type: String
      label: "building_id"
      max: 50

    name:
      type: String
      label: "Name"
      optional: true
      max: 50

    creation_date:
      type: Date
      label: "Creation date"
      defaultValue: new Date()
)

出版物:/server/publications.coffee

# Buildings

    Meteor.publish "allBuildings", ->
      Buildings.find()

    Meteor.publish "todayBuildings", ->
      Buildings.find creation_date:
        $gte: moment().startOf("day").toDate()
        $lt: moment().add("days", 1).toDate()



    # Publish a single item
    Meteor.publish "singleBuilding", (id) ->
      Buildings.find id


    # Spaces
    # Publish all items
    Meteor.publish "allSpaces", ->
      Spaces.find()

编辑2

经过一些研究,我终于想出了一个解决方案:

Template.spacesList.helpers
  spaces: () ->
    if Router._currentController.params._id
      subs.subscribe "buildingSpaces", Router._currentController.params._id
      Spaces.find()
    else
      subs.subscribe "allBuildings"
      Spaces.find()
  nbr_spaces: () ->
    Spaces.find().count()

另附出版物:

# Publish all items for building
Meteor.publish "buildingSpaces", (building_id) ->
  Spaces.find({building_id: building_id})

错误是:

  • 空间定义未包装到函数中的事实
  • 我用不太性感的Router._currentController.params._id代替了@ params._id,但是我找不到任何捷径.

我仍然不知道这是否是管理嵌套路由的最佳方法.

还有更好的建议吗?

解决方案

在经历了许多不同的选择之后,我终于找到了一个铁路由器的选择,我以前没有注意到.这真是神奇.

使用yields可以更轻松地实现嵌套路由(至少有两个级别(我没有尝试更多级别)):

我的路线是这条路线:

Router.map ->
  @route "buildingSpaces",
    path: "/buildings/:_id/spaces"
    template: "building"
    yieldTemplates: {
      'buildingSpaces': {to: "subTemplate"}
    }
    waitOn: ->
      [subs.subscribe("allSpaces"),
       subs.subscribe "allBuildings"]

    data: ->
      building: Buildings.findOne(@params._id)
      spaces: Spaces.find({building_id: @params._id})

这些是我的模板:

template(name="building")
    .animated.fadeIn
        +with building
                .building
                    .page-header.position-relative
                        h1.inline #{name}
                    .row
                        .col-xs-12
                            .tabbable
                                ul.nav.nav-tabs
                                    li#menu-spaces(class="{{isActive 'buildingSpaces'}}")
                                        a(href="{{pathFor 'buildingSpaces'}}") #{nbr_spaces} Spaces
                                    li#menu-dashboards(class="{{isActive 'buildingDashboards'}}")
                                        a(href="{{pathFor 'buildingDashboards'}}") Dashboards
                                .tab-content
                                    +yield "subTemplate"


template(name="buildingSpaces")
    .animated.fadeInDown
        .page-header.position-relative
            a.btn.btn-info.btn-sm#newSpaceButton
                i.ace-icon.fa.fa-plus
                | New space
        .clearfix
        +spacesList

template(name="spacesList")
    .widgets
        .row
            +each spaces
                .col-xs-12.col-sm-6
                    .widget-box.widget-color-purple
                        .widget-header
                            a(href="{{pathFor 'space'}}") #{name}
                        .widget-body
                            p Content here
    +insertSpaceForm

最后,我有一个助手来管理菜单:

Handlebars.registerHelper "isActive", (template) ->
  currentRoute = Router.current().route.name
  if currentRoute and template is currentRoute then "active" 
  else ""

非常光滑.单击子菜单时,它仅加载子模板.这是我发现的最好的...

希望这对您有帮助...

I have two meteor collections with a one-to-many relationship: buildings and spaces

On my building page, I want to show the spaces related to the building.

For now, I did it this way:

buildingsRoute.coffee
    BuildingController = RouteController.extend(template: "buildings")
    Router.map ->
      @route "building",
        path: "/buildings/:_id"
        waitOn: ->
          subs.subscribe "allBuildings"
          subs.subscribe "allSpaces"

        data: ->
          building: Buildings.findOne(@params._id)
          spaces: Spaces.find({building_id: @params._id})

building.jade:

template(name="building")
        +with building
            .building
                .page-header.position-relative
                    h1.inline #{name}
                .row
                    .col-xs-12
                       +spacesList

template(name="spacesList")
    .widgets
        .row
            h1 Spaces
            +each spaces
                .col-xs-12.col-sm-6
                    .widget-box.widget-color-purple
                        .widget-header
                            a(href="{{pathFor 'space'}}") #{name}
                        .widget-body
                            p Content here

This doesn't work as such, I guess because the data context of the spacesList template is not the same as the one defined by iron router for building.

I could replace "+each spaces" by "+each ../spaces" but this doesn't seem like a very generic solution to me (what if I want to use my spaceslist template in another context?)

So I tried to define the data context in template helpers like this:

Template.spacesList.helpers
  spaces: Spaces.find({building_id: @params._id})

But I get the error message:

Spaces is not defined.

So I'm a bit confused. What is the meteor way to implement nested routes properly?

Thank you!

EDIT:

Definition of Spaces collection: /models/space.coffee

@Spaces = new Meteor.Collection("spaces",
  schema:
    building_id:
      type: String
      label: "building_id"
      max: 50

    name:
      type: String
      label: "Name"
      optional: true
      max: 50

    creation_date:
      type: Date
      label: "Creation date"
      defaultValue: new Date()
)

Publications: /server/publications.coffee

# Buildings

    Meteor.publish "allBuildings", ->
      Buildings.find()

    Meteor.publish "todayBuildings", ->
      Buildings.find creation_date:
        $gte: moment().startOf("day").toDate()
        $lt: moment().add("days", 1).toDate()



    # Publish a single item
    Meteor.publish "singleBuilding", (id) ->
      Buildings.find id


    # Spaces
    # Publish all items
    Meteor.publish "allSpaces", ->
      Spaces.find()

EDIT 2

After some researches, I finally came up with a solution:

Template.spacesList.helpers
  spaces: () ->
    if Router._currentController.params._id
      subs.subscribe "buildingSpaces", Router._currentController.params._id
      Spaces.find()
    else
      subs.subscribe "allBuildings"
      Spaces.find()
  nbr_spaces: () ->
    Spaces.find().count()

With an additional publication:

# Publish all items for building
Meteor.publish "buildingSpaces", (building_id) ->
  Spaces.find({building_id: building_id})

The errors were:

  • the fact that the space definition wasn't wrapped into a function
  • the @params._id that I replaced by the not very sexy Router._currentController.params._id but I couldn't find any shortcut for this.

I still don't know whether this is the Meteor (best) way to manage nested routes...

Any better recommendation?

解决方案

After going through a whole lot of different options, I finally found an option of iron-router that I didn't notice before. This makes the magic.

The implementation of nested routes (at least with two levels (I didn't try more levels)) becomes much easier with the use of yields:

My route is this one:

Router.map ->
  @route "buildingSpaces",
    path: "/buildings/:_id/spaces"
    template: "building"
    yieldTemplates: {
      'buildingSpaces': {to: "subTemplate"}
    }
    waitOn: ->
      [subs.subscribe("allSpaces"),
       subs.subscribe "allBuildings"]

    data: ->
      building: Buildings.findOne(@params._id)
      spaces: Spaces.find({building_id: @params._id})

These are my templates:

template(name="building")
    .animated.fadeIn
        +with building
                .building
                    .page-header.position-relative
                        h1.inline #{name}
                    .row
                        .col-xs-12
                            .tabbable
                                ul.nav.nav-tabs
                                    li#menu-spaces(class="{{isActive 'buildingSpaces'}}")
                                        a(href="{{pathFor 'buildingSpaces'}}") #{nbr_spaces} Spaces
                                    li#menu-dashboards(class="{{isActive 'buildingDashboards'}}")
                                        a(href="{{pathFor 'buildingDashboards'}}") Dashboards
                                .tab-content
                                    +yield "subTemplate"


template(name="buildingSpaces")
    .animated.fadeInDown
        .page-header.position-relative
            a.btn.btn-info.btn-sm#newSpaceButton
                i.ace-icon.fa.fa-plus
                | New space
        .clearfix
        +spacesList

template(name="spacesList")
    .widgets
        .row
            +each spaces
                .col-xs-12.col-sm-6
                    .widget-box.widget-color-purple
                        .widget-header
                            a(href="{{pathFor 'space'}}") #{name}
                        .widget-body
                            p Content here
    +insertSpaceForm

And finally, I have a helper to manage my menu:

Handlebars.registerHelper "isActive", (template) ->
  currentRoute = Router.current().route.name
  if currentRoute and template is currentRoute then "active" 
  else ""

It's quite slick. It loads only the subTemplate when clicking the submenu. It's the best I found...

Hope this helps...

这篇关于流星铁路由器嵌套的路线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆