簡體   English   中英

如何基於商店信息和模型具有許多關系在控制器中創建計算屬性

[英]How to create computed attribute in controller based on store information and model hasMany relationship

我有一個對象“模塊”類型的模型。 簡化后,它是這樣的:

App.Module = DS.Model.extend({
    name: DS.attr('string'),
    orModules: DS.hasMany('module', { inverse: null }),  // reflexive relship
});

Module的視圖中,應該有一個不是當前model ,也不包含在model.orModules中的所有Module記錄的列表。 我認為此信息不屬於App.Module而是屬於App.ModuleController

問題在於,我仍然對DS.PromiseArray和異步內容以及EmberDS的“類”(如DS.PromiseArray

好,這是我的嘗試:

App.ModuleController = Ember.Controller.extend({

    availableModules: function () {
        var thisModule = this.get('model');  
        var allModules = this.store.findAll('module');  // this is a promise, right?
        var orModules = thisModule.get('orModules');  // this as well, more exactly a `DS.PromiseArray`, right?

        return DS.PromiseArray.create({
            promise: Ember.RSVP.hash({allMods: allModules, orMods: orModules}, function (res) {
                // Here I guess both promises are fulfilled, so I 
                // have access to all data

                // But, first problem res.allMods and res.orMods have different interfaces. 
                // I can access res.allMods.content for the Module objects, and call mod.get('id'), but I have trouble transversing res.orMods.

                // And the second and big problem is, I don't know what should I return.
                // even returning some hardcoded value raises an exception 
                // "Assertion Failed: ArrayProxy expects an Array or Ember.ArrayProxy, but you passed object
                return [{id: 666, name: '666'}];
            })

        });

    }.property('model.orModules'),

});

因此,如您所見,我很困惑。 有什么幫助嗎? 提前致謝。

您應該同時提供路線中的當前模塊和其他模塊:

return Ember.RSVP.hash({
  modules:       allModulesPromise,
  currentModule: currentModulePromise
});

您可以從模塊中提取當前模塊,例如:

App.IndexRoute = Ember.Route.extend({
  model () {   
    let allModulesPromise = this.store.find('module');

    let currentModulePromise = allModulesPromise.then(
      // Whatever way you use to identify which module is the current
      modules => modules.findBy('id', '1')
    );

    return Ember.RSVP.hash({
      modules:       allModulesPromise,
      currentModule: currentModulePromise
    });
  }
});

有了modulescurrentModule ,過濾掉其他模塊變得很簡單:

App.IndexController = Ember.Controller.extend({
  availableModules: Ember.computed(
    'model.currentModule.children.@each.id',
    'model.modules.@each.id',
    function() {
      let currentModule = this.get('model.currentModule');
      let children      = currentModule.get('children');

      return this
        .get('model.modules')
        .filter( module => (
          module !== currentModule
          && !children.contains(module)
        ));
    }
  )
});

演示: http : //emberjs.jsbin.com/woqofo/3/edit?html,js,output

更新以回應評論

當路由的model鈎子返回非承諾時,路由會立即將返回的值傳遞給控制器​​,然后控制器將呈現模板。

但是,當model掛鈎返回承諾時,路由將進入“加載”狀態並等待承諾解決。 當它與一個特定值解析, 路由經過的值到控制器以呈現與該模板。

因此,您無需在控制器中處理承諾! 您已經解析了要渲染的數據。

您可以在控制器中執行Ajax請求,但是為什么要麻煩呢? 相反,您可以使用URL參數和查詢參數在URL中反映當前模型。 如果這樣做,則每當URL更改時,路由就會更新控制器上的model屬性。

要獲取一些不屬於URL的任意數據,請使用服務。

TL / DR:避免在控制器/組件中聲明諾言(執行Ajax請求),您的生活將會更加幸福。 :d

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM