Break up my application.handlebars into separate templates using Ember.js and Ember.Router

丶灬走出姿态 提交于 2019-12-21 06:08:28

问题


I'm building a front-end (on top of Ruby on Rails) using ember.js and the ember-rails gem.

My (ember) application consists of Models, Views, Controllers and an application.handlebars template which describes my UI.

Whats the best practice to break up this application.handlebars file so that I can manage the UI? For example, I'd like to have Navigation at the top of the page.

I've tried using the Ember.Router, a separate navigation.handlebars (with NavigationView and NavigationController) the {{outlet}} helper to no avail. Here's what the Router looks like:

App.Router = Ember.Router.extend(
  enableLogging:  true
  root: Ember.Route.extend(
    index:
      route: '/'
      connectOutlets: (router, context) =>
        router.get('applicationController').connectOutlet('navigation')
)

and the application.handlebars

<h1>Lots of HTML that I want to break up</h1>
{{outlet}}

Let me know if you need more info...thanks.


回答1:


As per my Understanding, Let's suppose you want 3 sections(can be any number) Header, Content & Footer, You can do something as follows

<script type="text/x-handlebars" data-template-name="application">
  {{view MyApp.HeaderView}}
  {{#view MyApp.ContentView}}
    {{outlet}}
  {{/view}}
  {{view MyApp.FooterView}}
</script>

<script type="text/x-handlebars" data-template-name="app-header">
  All your Header related HTML
</script>

<script type="text/x-handlebars" data-template-name="app-content">
  HTML related to content
  {{yield}} //this will be explained at the end
  More HTML if you want
</script>

<script type="text/x-handlebars" data-template-name="app-footer">
  HTML related to footer
</script>

MyApp.HeaderView = Ember.View.extend({
  templateName: 'app-header'
})


MyApp.ContentView = Ember.View.extend({
  templateName: 'app-content'
})

MyApp.FooterView = Ember.View.extend({
  templateName: 'app-footer'
})

MyApp.ApplicationView = Ember.View.extend({
  templateName: 'application'
})


explaining {{yield}} In a nutshell, whatever is between in the block helper of a given view goes in there, In the above example for the MyApp.ContentView, the {{outlet}} defined in the {{#view MyApp.ContentView}} handlebars gets inserted at the {{yield}}

On the similar lines let me show the difference between layoutName property & templateName property,

App.someView = Ember.View.extend({
  tagName: 'a',
  templateName: 'a-template',
  layoutName: 'a-container'
})

<script type="text/x-handlebars" data-template-name="a-template">
  Hi There
</script>

<script type="text/x-handlebars" data-template-name="a-container">
  <span class="container">
    {{yield}}
  </span>
</script>


Will result in following HTML

  <a class="ember-view" id="ember235">
    <span class="container ember-view" id="ember234">
      Hi There
    </span>
  </a>

Use these concepts to split the application handlebars in your case it would be something like

{{view App.NavigationView}}
{{outlet}}

Update as per latest ember

The new ember supports partials similar to rails, now we can modify the above to use {{partial}} as follows:

{{partial "header"}}
{{outlet}}
{{partial "footer"}}

Ember when encountered this template will look for the template whose name is _header(similar to rails) and inserts the template(same goes for footer)

And If want to associate a controller we can use {{render}} helper

{{render "sidebar"}}

inserts the template whose name is sidebar at specified location in handlebars besides it also associates App.SidebarController to it,
Note: we cannot use {{render 'sidebar'}} more than once in same handlebars file.

But again if you want to use a widget like view multiple places in a given page then use {{view}} helper




回答2:


For this problem, what you need to do is think about what views change and where that changes happen. If for example you have a navigation section and a main section, then think about how each of these sections change with the state of your application. Be sure to only create an {{outlet}} for dynamic content, otherwise things will get messy and the application will be slower. Then setup your templates and your router similar to the example below.

Templates:

<script type="text/x-handlebars" data-template-name="application">
    <!--Your application template goes here-->
    {{outlet navigation}}
    {{outlet body}}
</script>
<script type="text/x-handlebars" data-template-name="navigation">
    <!--Your navigation template goes here-->
</script>
<script type="text/x-handlebars" data-template-name="main-one">
    <!--Your mainOne template goes here-->
</script>
<script type="text/x-handlebars" data-template-name="main-two">
    <!--Your mainTwo template goes here-->
</script>

Note: You can have {{outlet}} in any of your view templates to change in more sub-states

Javascript:

window.App = Em.Application.create({
    ApplicationView: Em.View.extend({
        templateName: "application"
    }),
    ApplicationController: Em.Controller.extend({
    }),
    NavView: Em.View.extend({
        templateName: "navigation"
    }),
    NavController: Em.Controller.extend({
    }),
    MainOneView: Em.View.extend({
        templateName: "main-one"
    }),
    MainOneController: Em.Controller.extend({
    }),
    MainTwoView: Em.View.extend({
        templateName: "main-two"
    }),
    MainTwoController: Em.Controller.extend({
    })
    Router: Em.Router.extend({
        root: Em.Route.extend({
            index: Em.Route.extend({
                route: '/',
                connectOutlets: function(router,context) {
                    router.get("applicationController").connectOutlet("navigation","nav");
                    router.get("applicationController").connectOutlet("body","mainOne");
                }
            }),
            otherState: Em.Route.extend({
                route: '/other-state',
                connectOutlets: function(router,context) {
                    router.get("applicationController").connectOutlet("navigation","nav");
                    router.get("applicationController").connectOutlet("body","mainTwo");
                }
            }),

        })
    })
});
App.initialize();

Note: The applicationController must extend Controller and not ObjectController or ArrayController



来源:https://stackoverflow.com/questions/14079791/break-up-my-application-handlebars-into-separate-templates-using-ember-js-and-em

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!