在父模板外部渲染ember组件

时间:2014-06-11 08:11:36

标签: javascript html css ember.js javascriptmvc

想象一下以下情况。我有一个绝对定位的侧边栏,然后在侧边栏中放置了一些更多的东西。在该侧边栏中,我有一个显示菜单的按钮,模板如下所示:

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

我喜欢这个解决方案并希望保留的是模板中的菜单定义在按钮旁边,这样可以保持良好的可维护性。

问题在于我希望菜单相对于视口定位,即渲染到document.body并使用绝对位置定位。这样它将呈现到侧边栏并导致滚动条可见,因为我已经通过其中一个父元素中的位置相对重置了定位上下文。

我有什么方法可以保持{{view App.MyMenu}}现在的位置,但让它渲染到身体(可能使用插座或其他机制)?这种情况的推荐模式是什么?

1 个答案:

答案 0 :(得分:12)

有很多方法可以在ember中使用相关上下文呈现视图。我提出了四种方法(我认为第一种方法更有可能是你想要的)

1. 如果视图需要放置在手柄模板之外的某个位置,则可以使用jQuery将呈现的内容放置在需要的位置。

(因为视图元素的替换发生在didInsertElement之后,可能还需要添加样式以不显示元素,例如display:none,并在重新定位后显示它)

示例 http://emberjs.jsbin.com/gotabore/1/edit

2。如果该地点位于另一个模板中的某个位置,请使用{{render}}帮助器将视图渲染到位。虽然我不确定上下文要求,但这个助手非常灵活(http://emberjs.com/guides/templates/rendering-with-helpers/#toc_the-code-render-code-helper)。

示例 http://emberjs.jsbin.com/xibayava/1/edit

3。使用{{outlet}}帮助程序根据访问route中指定的内容呈现视图。 (http://emberjs.com/guides/routing/rendering-a-template/

示例 http://emberjs.jsbin.com/tiyuqenu/1/edit

4. 使用ContainerView以编程方式将视图推送到需要的位置。

示例 http://emberjs.jsbin.com/yoyujeqi/1/edit


方法4的更新: 对于等于或大于1.8.x的版本,为了避免http://emberjs.com/guides/deprecations/#toc_global-lookup-of-views中提到的错误,可以指定与之关联的属性ContainerView,如以下示例所示

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


相关代码

接近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"]
});

接近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"
});

接近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"
});

接近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"
});

方法4的更新:

<强> JS

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

<强> HBS

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