在{{#linkTo}}点击期间没有方法'addArrayObserver'

时间:2013-03-02 17:04:38

标签: ember.js

嘿不确定是否有人可以帮助我,但我一直在努力解决这个错误:

"Uncaught TypeError: Object <App.AssetType:ember408:2> has no method 'addArrayObserver'"

以下是{{#linkTo}}的模板,点击后会产生此错误

<div class="row">
  <div class="twelve columns">
    <h2>{{title}} - Assets</h2>
  </div>
</div>
<div class="row">
  <div class="three columns">
    <ul>
      {{#each assetTypes}}
      {{#linkTo 'product.filter' this}}{{title}}{{/linkTo}}
      {{/each}}
    </ul>
  </div>
  <div class="nine columns">
    {{outlet}}
  </div>
</div>

和应用程序代码

window.App = Ember.Application.create
  rootElement: '.solution_products_documents'

App.ApplicationRoute = Ember.Route.extend
  model: ->
    App.Product.find()
App.ApplicationController = Ember.ArrayController.extend
  sortProperties: ['title']

App.ProductRoute = Ember.Route.extend
  model: (params) ->
    App.Product.find params.product_id
  setupController: (controller, model) ->
    controller.set 'documents', model.get 'document_ids'

App.ProductController = Ember.ObjectController.extend
  assetTypes: (->
    docs = @get('documents')
    docs.getEach 'asset_type_id'
  ).property('documents')

App.ProductFilterRoute = Ember.Route.extend
  model: (params) ->
    type = App.AssetType.find params.asset_type_id
    product = this.modelFor 'product'
    docs = product.get 'document_ids'
    model = docs.filterProperty 'asset_type_id', type
App.ProductFilterController = Ember.ArrayController.extend()

App.Router.map ->
  @route 'index', { path: '/' }
  @resource 'product', { path: '/products/:product_id' }, ->
    @route 'filter', { path: '/filter-by/:asset_type_id' }

##
# MODELS / EMBER-DATA
##

serializer = DS.JSONSerializer.create()

serializer.configure 'App.Document',
  sideloadAs: 'documents'

serializer.configure 'App.AssetType',
  sideloadAs: 'asset_types'

serializer.configure 'App.Product',
  sideloadAs: 'products'

App.RestAdaptor = DS.RESTAdapter.extend
  serializer: serializer
  namespace: URL.slice 1
DS.Store.extend(
  adapter: App.RestAdaptor
  revision: 11
).create()

App.Product = DS.Model.extend
  title: DS.attr 'string'
  document_ids: DS.hasMany 'App.Document'

App.Document = DS.Model.extend
  title: DS.attr 'string'
  product_id: DS.belongsTo 'App.Product'
  asset_type_id: DS.belongsTo 'App.AssetType'

App.AssetType = DS.Model.extend
  title: DS.attr 'string'
  document_ids: DS.hasMany 'App.Document'

######### /> END MODELS #################

如果我将网址#/products/4/filter-by/2放入地址栏,那么一切都按计划进行。只有当我点击{{#linkTo}}时才会出现此错误并且内容未显示。在它到达App.ProductFilterRoute之前抛出错误,因为路由中的debugger语句没有被执行,但它在页面刷新时。

非常感谢任何帮助或方向,因为我真的不知道在哪里看。

更新

如果我不使用{{#linkTo}}助手而是手动构建网址

<a href="#/products/{{unbound controller.content.id}}/filter-by/{{unbound this.id}}">{{title}}</a>

一切正常。 linkTo和manual href之间有什么不同?

2 个答案:

答案 0 :(得分:6)

当您导航到ProductFilterRoute时,错误基本上表示Ember需要一个数组。

为什么Ember期望在这里使用数组?

  1. 您的Route(ProductFilterController)控制器的类型为ArrayController
  2. 我对coffeescript不太熟悉,但你的模型钩子似乎也会返回一个数组。 重要提示:只有在通过网址输入您的应用时才会执行模型挂钩。(这就是为什么您的手动导航由Url和href都有效。来自EmberDoc的引用:“一个钩子你可以实现将URL转换为此路由的模型。“)
  3. 为什么会抛出错误? 所以你的路线围绕着一个阵列。你只是传递一个普通的对象。因此,黄金法则是:将相同的数据结构(在本例中为数组)传递给您的{{linkTo}}助手,该助手由模型钩子实现返回。

    可能的解决方案:

    1. 使用操作代替{{linkTo}}
    2. 在您的路线中实施一项操作,找到具有给定asset_type的所有文档并将其传递给您的路线。
    3. 对模板的修改:

      <a {{action 'filterProductByAsset' this}}> {{title}} </a>
      

      ProductFilterRoute的扩展程序:

      events:{
          filterProductByAsset : function(assetTypeId){
              type = App.AssetType.find(asset_type_id);
              product = this.modelFor('product');
              docs = product.get('document_ids');
              models = docs.filterProperty('asset_type_id', type);
              this.transitionTo("product.filter", models)
          }
      }
      

答案 1 :(得分:1)

我怀疑这是问题所在:

assetTypes: (->
  docs = @get('documents')
  docs.getEach 'asset_type_id'
).property('documents')

这看起来会像这样生成一个数组:

[1,2,3,4,5]

当你真的需要一个响应id的对象数组时,例如

object1 = Em.Object.create id: 1
object2 = Em.Object.create id: 2
[object1, object2] #etc

如果要更改此行为,则需要查看将链接到的路径的序列化挂钩,在本例中为product.filter

关于{{linkTo}}与手动创建的链接,linkTo帮助程序已启用js,您应始终使用它而不是手动链接。使用HistoryLocation / pushState支持时,这会成为一个真正的问题,因为它会强制重新加载整页。

这里还有另一个问题:你无法观察到这样的文件。您必须使用property('documents.@each')

之类的内容