2012-09-26 184 views
10

我正在用EmberJS v1.0.pre編寫一個應用程序。我有一個ArrayController其中包含所有人的列表。有一堆嵌套的視圖顯示了每個寵物的人,他們的寵物和筆記。EmberJS嵌套視圖和控制器

|----------------------------------------| 
| John         | <- Person 
|----------------------------------------| 
| Quincy (Dog)       | <- Pet 
|  - Super ornery      | <- Note 
|  - Likes XYZ Dog food    | 
|  - Will eat your socks    | 
|          | 
| Tom (Cat)       | 
| - Always (not) catching mice  | 
|          | 
|----------------------------------------| 
| Roger         | 
|----------------------------------------| 
| V (Dog)        | 
| - Likes XYZ Dog food    | 
| - Sneezes, but it's ok    | 
|          | 
|----------------------------------------| 
| ...         | 

從感覺應該有每個孩子的控制,但我無法弄清楚如何實現,在灰燼純MVC立場。有頂級的數組控制器,然後是所有單獨的視圖。如果我想刪除一個筆記,或編輯它,似乎我需要將視圖的上下文傳遞給控制器​​。

// in the view 
click: function() { 
    this.get('controller').updateNote(this.get('content')) 
} 

這對我來說真的很不好,視圖不應該是數據的權威來源。我的假設是ArrayController會實例化一個itemControlerClass以及itemViewClass

更新:我創建了一個fiddle以更好地說明我的問題。該功能故意不完整,目的是通過點擊列表上的項目時增加內容來完成功能。

更新:對不起,我在意外刪除了小提琴!我正在做一些最終解決方案的工作,所以我會嘗試創建一個新的小提琴解決方案。

+0

查看http://emberjs.com/guides/outlets/ –

+0

該指南中沒有關於我的問題的真實公司信息。我已經閱讀過,我會繼續提及它,但還沒有發現任何東西。 – noazark

+0

檢查出來,然後http://stackoverflow.com/questions/12595496/how-can-i-build-a-recursive-view-in-ember/12602743#comment17008361_12602743 –

回答

12

「從單純的MVC角度來看感覺應該爲每個孩子控制器」

你並不需要爲每個項目的控制,而是對對象的每個集合的ArrayController (人物,寵物,筆記)。順便說一下,對子對象(狗,筆記)的任何操作都不應傳遞給App.PersonsController。這將打破Separation of Concerns原則。

Ember.Router文檔涵蓋了您希望在單個對象中嵌套視圖的情況(例如/:people_id)。但是你想爲一組對象嵌套視圖。我想不到嵌套{{outlet}}意見的方法,但您可以執行以下操作:

將對象加載到3個ArrayControllers中的People,Pets,Notes以及將子對象的操作委託給其對應的ArrayController。

App.Router = Ember.Router.extend({ 
    root: Ember.Route.extend({ 
    route: '/', 
    persons: Ember.Route.extend({ 
     connectOutlets: function(router) { 

      router.get('applicationController').connectOutlet('persons'); 
      // App.Note.find() fetches all Notes, 
      // If you are not using ember-data, make sure the notes are loaded into notesController 
      router.set('notesController.content', App.Note.find()); 
      router.set('petsController.content', App.Pet.find()); 
     } 
    }) 
    }) 
}); 

然後你people模板應該是這樣的:

{{#each person in people}} 
    <h1>My name is {{person.name}}</h1> 

    {{#each pet in person.pets}} 
    I have a pet with name {{pet.name}} 
    <a {{action delete pet target="App.router.petsController">Delete pet</a> 
    {{/each}}  

    {{view Ember.TextField valueBinding="myNewPetName" type="text"}} 
    <a {{action create myNewPetName person target="controller"}}> 
    Add a new pet for this person 
    </a> 


    {{#each note in person.notes}} 
    <!-- delete, create, edit ... --> 
    {{/each}} 

正如你所看到的,在子對象的動作都被委託給它的控制器(寵物 - > petsController),傳遞對象作爲上下文。在create動作的情況下,控制器需要知道寵物belongsTo的哪個人。因此,我們通過2個上下文:人物和寵物的屬性(爲了簡單起見,我只是假定寵物的名字)。

在你App.petsControllers你應該有行動沿線:

App.PetsController = Ember.ArrayController.extend({ 
    delete: function(e) { 
    var context = e.context; 
    this.get('content').removeObject(context); 
    // Also, if you use ember-data, 
    // App.Pet.deleteRecord(context); 
    }, 

    create: function(e) { 
    var petName = e.contexts[0] 
    var person = e.contexts[1]; 
    this.get('content').pushObject({name: petName, person: person}); 
    // with ember-data: 
    // App.Pet.createRecord({name: petName, person: person}); 
    } 
}); 
+1

這是我見過的最完整的例子,謝謝!我會採取這個答案,並與它一起運行。我仍然需要解決一些問題。從視圖傳遞上下文是我對這個問題的原始投訴,但似乎不可避免。另外,控制器不能簡單地設置爲所有的Notes,因爲它們是Pets(寵物)和Pets(寵物)中的孩子。對我來說,這不像是一個建築問題。我需要首先設置父上下文。我會用我發現的任何更新來更新我的問題。再次感謝。 – noazark

1

你應該使用網點。 它們是可以用不同的控制器處理的Ember視圖中的小佔位符。

上面的鏈接上有一個公正的解釋,你已經檢查並沒有發現任何東西。但在你回到那之前,請先閱讀:http://trek.github.com/

如果其中任何一個仍然不能幫助你,讓我們知道,我會爲你組裝一個樣品。

+0

我已經閱讀了兩篇文章,甚至在發佈之前。我也在使用網點,但網點不會將內容的責任委託給單獨的控制器。感謝您提供一個例子,我很樂意看到一個例子。我也會在jsfiddle中掀起一些東西來更好地解釋我的問題。 – noazark

+0

我用[小提琴](http://jsfiddle.net/noazark/HmHK3/)更新了我的問題。感謝您的持續幫助。 – noazark

1

我認爲this是你正在尋找的東西,看一看,它是非常簡單的,你也可以檢查this的例子。基本上,你可以實現你想要的插座,路由器和連接你的所有網點的行動。

+0

我會再試一次。這篇文章https://gist.github.com/3002177也有很大的幫助。我認爲我的問題一直在使用ArrayController。當真的它應該只是一個帶有插座的控制器?那有意義嗎? – noazark

+0

你有沒有可能提供一個不同的,更相關的例子?你提供的那個與我的問題沒有任何關係。具體來說,我的問題不是路由,而是關於委託控制嵌套資源。奧特萊斯有趣,但即使有所有使用它們的建議,仍然沒有有用的例子說明他們如何解決我的問題。 – noazark

0

我是新來的灰燼,並一直在尋找一種方式做同樣的事情。在頂層ArrayController,我只是用itemController財產,它的偉大工作:

App.PeopleController = Ember.ArrayController.extend({ 
    itemController: "Person" 
}); 

App.PersonController = Ember.ObjectController.extend //... 

我的完整的解決方案是在this js fiddle。不幸的是,我得到的PetController實例的工作方式似乎對我很不利。

+0

自v1.0pre以來的更新已經超級有用,我的運氣也好多了。我會更深入地研究你所做的事情,看看它是如何發展的! – noazark