Rendu du composant de braise en dehors du modèle parent

Imaginez la situation suivante. J'ai une barre latérale positionnée absolument, puis d'autres choses placées absolument dans cette barre latérale. Dans cette barre latérale, j'ai un bouton, qui montre un menu, le modèle ressemble à ceci:

<button>Click me</button> {{#if shouldDisplayMenu}} {{view App.MyMenu}} {{/if}} 

Ce que j'aime à propos de cette solution et que je veux conserver, c'est que le menu du modèle est défini juste à côté du bouton, ce qui permet une bonne maintenance.

Le problème est que je souhaite que le menu soit positionné par rapport à la fenêtre, c'est-à-dire rendu dans document.body et positionné avec la position absolue. De cette façon, il sera rendu dans la barre latérale et provoquera une visibilité de la barre de défilement car j'ai déjà réinitialisé le contexte de positionnement par position relative dans l'un des éléments parents.

Est-ce que je peux garder {{view App.MyMenu}} où il est maintenant, mais le faire rendre au corps (peut-être en utilisant des points de sortie ou un autre mécanisme)? Quel est le modèle recommandé pour une situation comme celle-ci?

Il existe de nombreuses façons de faire apparaître des vues dans un contexte apparenté. Je présente quatre approches (je pense que la première est plus probable que ce que vous recherchez) :

1. Si la vue doit être placée quelque part hors d'un gabarit de guidon, il est possible d'utiliser jQuery pour placer le contenu rendu partout où il est nécessaire.

( didInsertElement le remplacement de l'élément de vue se produit après didInsertElement il est probablement nécessaire d'ajouter des styles pour ne pas afficher l'élément, par exemple, l' display:none et le montrer après avoir été repositionné)

Exemple http://emberjs.jsbin.com/gotabore/1/edit

2. Utilisez {{render}} helper pour rendre la vue en place si cet endroit est quelque part dans un autre modèle. Même si je ne suis pas certain des exigences du contexte, cet assistant est assez flexible ( http://emberjs.com/guides/templates/rendering-with-helpers/#toc_the-code-render-code-helper ).

Exemple http://emberjs.jsbin.com/xibayava/1/edit

3. Utilisez {{outlet}} helper pour rendre la vue en fonction de ce qui est spécifié dans l' route visité. ( http://emberjs.com/guides/routing/rendering-a-template/ )

Exemple http://emberjs.jsbin.com/tiyuqenu/1/edit

4. Utilisez un ContainerView pour afficher une vue de manière programmée partout où il est nécessaire.

Exemple http://emberjs.jsbin.com/yoyujeqi/1/edit


MISE À JOUR pour l'approche 4: pour des versions égales ou supérieures à 1.8.x, pour éviter l'erreur mentionnée dans http://emberjs.com/guides/deprecations/#toc_global-lookup-of-views , il est possible de spécifier une propriété associée Au ContainerView comme indiqué dans l'exemple suivant

http://emberjs.jsbin.com/difayakeki/1/edit?html,js,output


Code connexe

Approche 1

Hbs

 <script type="text/x-handlebars"> <h2> Welcome to Ember.js</h2> {{outlet}} </script> <script type="text/x-handlebars" data-template-name="index"> This is index<br/> {{view App.TestView}} </script> <script type="text/x-handlebars" data-template-name="test"> This is the test view<br/> <b>{{myProp}}</b> </script> <div id="a-div" style="background-color:lightgray"> This is a div somewhere,<br/> </div> 

Js

 App = Ember.Application.create(); App.Router.map(function() { // put your routes here }); App.IndexController = Ember.Controller.extend({ myProp:"index controller prop" }); App.IndexView = Ember.View.extend({ placeTestViewSomewhere:function(){ var theTestView = this.$(".my-test-view").detach(); $("#a-div").append(theTestView); }.on("didInsertElement") }); App.TestView = Ember.View.extend({ templateName:"test", classNames:["my-test-view"] }); 

Approche 2

Hbs

 <script type="text/x-handlebars"> <h2> Welcome to Ember.js</h2> {{outlet}} </script> <script type="text/x-handlebars" data-template-name="index"> This is index<br/> <div style="background-color:lightgray"> This is a div in index template with render helper,<br/> {{render "test"}} </div> </script> <script type="text/x-handlebars" data-template-name="test"> This is the test view<br/> <b>{{myProp}}</b> </script> 

Js

 App.IndexView = Ember.View.extend({ placeTestViewSomewhere:function(){ // var theTestView = this.$(".my-test-view").detach(); // $("#a-div").append(theTestView); }.on("didInsertElement") }); App.TestController = Ember.Controller.extend({ myProp:"test controller prop" }); App.TestView = Ember.View.extend({ templateName:"test" }); 

Approche 3

Hbs

 <script type="text/x-handlebars"> <h2> Welcome to Ember.js</h2> {{outlet}} <div style="background-color:lightgray"> This is a div in application template with outlet helper,<br/> {{outlet "test-outlet"}} </div> </script> <script type="text/x-handlebars" data-template-name="index"> This is index<br/> </script> <script type="text/x-handlebars" data-template-name="test"> This is the test view<br/> <b>{{myProp}}</b> </script> 

Js

 App.IndexRoute = Ember.Route.extend({ renderTemplate: function() { this.render("index"); this.render('test', { // the template to render into: 'application', // the template to render into outlet: 'test-outlet' // the name of the outlet in that template }); } }); App.IndexView = Ember.View.extend({ placeTestViewSomewhere:function(){ // var theTestView = this.$(".my-test-view").detach(); // $("#a-div").append(theTestView); }.on("didInsertElement") }); App.TestController = Ember.Controller.extend({ myProp:"test controller prop" }); App.TestView = Ember.View.extend({ templateName:"test" }); 

Approche 4

Hbs

 <script type="text/x-handlebars"> <h2> Welcome to Ember.js</h2> {{outlet}} <div style="background-color:lightgray"> This is a div in application template with view helper and a view container,<br/> {{view Ember.ContainerView viewName="my-menu-container"}} </div> </div> </script> <script type="text/x-handlebars" data-template-name="index"> This is index<br/> </script> <script type="text/x-handlebars" data-template-name="test"> This is the test view<br/> <b>{{myProp}}</b> </script> 

Js

 App.IndexController = Ember.Controller.extend({ myProp:"index controller prop" }); App.IndexView = Ember.View.extend({ placeTestViewSomewhere:function(){ var theTestView = App.TestView.create({}); theTestView.set("context",this.get("context")); this.get("parentView.my-menu-container").pushObject(theTestView); }.on("didInsertElement") }); App.TestView = Ember.View.extend({ templateName:"test" }); 

MISE À JOUR pour l'approche 4:

Js

 App.ApplicationView = Em.View.extend({ containerView:Em.ContainerView }); 

Hbs

 {{view view.containerView viewName="my-menu-container"}}