2

誰かが私を助けることができるかどうかわかりませんが、私はこのエラーに長い間苦労してきました:

"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/2URLをアドレス バーに入力すると、すべてが計画どおりに機能します。{{#linkTo}}このエラーが発生してコンテンツが表示されないのは、をクリックしたときだけです。App.ProductFilterRouteルート内のステートメントが実行されていないため、エラーが発生する前にスローdebuggerされますが、ページの更新中です。

どこを見ればいいのかわからないので、どんな助けや指示も大歓迎です。

アップデート:

{{#linkTo}}ヘルパーを使用せず、代わりに手動で URL を作成する場合

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

すべて正常に動作します。linkTo と手動の href の違いは何ですか?

4

2 に答える 2

6

エラーは基本的に、ProductFilterRouteに移動するときに、Emberが配列を予期していることを示しています。

なぜEmberはここで配列を期待するのですか?

  1. ルートのコントローラー(ProductFilterController)のタ​​イプはArrayControllerです
  2. 私はcoffeescriptにあまり詳しくありませんが、モデルフックも配列を返すようです。重要なお知らせ:モデルフックは、URL経由でアプリに入るときに実行されます。(これが、Urlとhrefの両方による手動ナビゲーションが機能する理由です。EmberDocからの引用:「URLをこのルートのモデルに変換するために実装できるフック」)

エラーがスローされるのはなぜですか? したがって、ルートは配列を中心に展開します。プレーンオブジェクトだけを渡します。したがって、黄金律は次のとおりです。同じデータ構造(この場合は配列)を{{linkTo}}ヘルパーに渡します。これは、モデルフックの実装によって返されます。

考えられる解決策:

  1. {{linkTo}}の代わりにアクションを使用してください
  2. 指定されたasset_typeを持つすべてのドキュメントを検索し、それをルートに渡すアクションをルートに実装します。

テンプレートへの変更:

<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)
    }
}
于 2013-03-02T17:51:37.533 に答える
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')

于 2013-03-02T17:49:51.767 に答える