如何从 ember 中的子组件范围访问父组件范围? [英] how to access parent component scope from a child components scope in ember?

查看:33
本文介绍了如何从 ember 中的子组件范围访问父组件范围?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很好奇这在 ember 中是否可行.这是在 angular 中很容易做的事情( plunkr: http://plnkr.co/edit/O2e0ukyXdKMs4FcgKGmX?p=预览 ):

目标是为 api 消费者制作一个易于使用、通用、可重用的手风琴 api.

我希望调用者能够使用的 api 是这样的(就像 angular api):

{{#ember-accordion listOfAccordionPaneObjects=model}}{{#ember-accordion-heading}}标题模板 html {{accordionPaneObject.firstName}}{{/ember-accordion-heading}}{{#ember-accordion-body}}这是手风琴体 {{accordionPaneObject.lastName}}{{/ember-accordion-body}}{{/ember-accordion}}

这是我使用 angular 编写的一个工作示例:

<html ng-app="angular-accordion"><头><风格>.angular-accordion-header {背景色:#999;颜色:#ffffff;填充:10px;边距:0;行高:14px;-webkit-border-top-left-radius: 5px;-webkit-border-top-right-radius: 5px;-moz-border-radius-topleft: 5px;-moz-border-radius-topright: 5px;边框左上角半径:5px;边框右上角半径:5px;光标:指针;文字装饰:无;font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;字体大小:14px;}.angular-accordion-container {高度:100%;宽度:100%;}.angular-accordion-pane {填充:2px;}.angularaccordionheaderselected {背景色:#bbb;颜色:#333;字体粗细:粗体;}.angular-accordion-header:悬停{文字装饰:下划线!重要;}.angularaccordionheaderselected:hover {文字装饰:下划线!重要;}.angular-accordion-pane-content {填充:5px;溢出-y:自动;左边框:1px 实心 #bbb;右边框:1px 实心 #bbb;边框底部:1px 实心 #bbb;-webkit-border-bottom-left-radius: 5px;-webkit-border-bottom-right-radius: 5px;-moz-border-radius-bottomleft: 5px;-moz-border-radius-bottomright: 5px;边框左下角半径:5px;边框右下角半径:5px;}.angulardisabledpane {不透明度:.2;}</风格><body style="margin: 0;"><div style="height: 90%; width: 100%; margin: 0;"ng-controller="外控制器"><angular-accordion list-of-accordion-pane-objects="outerControllerData"><窗格><pane-header>Header {{accordionPaneObject}}</pane-header><pane-content>Content {{accordionPaneObject}}</pane-content></窗格></angular-accordion>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.js"></script><脚本>angular.module('angular-accordion', []).directive('angularAccordion', function() {var 模板 = '';返回 {限制:'E',转置:真实,替换:真的,模板:'

'+'<div ng-transclude class="angular-accordion-container" ng-repeat="accordionPaneObject in listOfAccordionPaneObjects"></div>'+'</div>',控制器:['$scope',函数($scope){var 窗格 = [];this.addPane = 函数(窗格){窗格.推(窗格);};}],范围: {listOfAccordionPaneObjects: '='}};}).directive('窗格', 函数() {返回 {限制:'E',转置:真实,替换:真的,模板:'<div ng-transclude class="angular-accordion-pane"></div>'};}).directive('paneHeader', function() {返回 {限制:'E',要求:'^angularAccordion',转置:真实,替换:真的,链接:功能(范围,iElement,iAttrs,控制器){控制器.addPane(范围);scope.toggle = function() {scope.expanded = !scope.expanded;};},模板:'<div ng-transclude class="angular-accordion-header" ng-click="toggle()"></div>'};}).directive('paneContent', function() {返回 {限制:'EA',要求:'^窗格标题',转置:真实,替换:真的,模板:'<div ng-transclude class="angular-accordion-pane-content" ng-show="expanded"></div>'};}).controller('outerController', ['$scope', function($scope) {$scope.outerControllerData = [1, 2, 3];}]);</html>

这里是我对 ember 做同样的事情:

index.html

<身体><script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.9/require.js" data-main="main.js"></script></html>

main.js

require.config({路径:{'ember': 'bower_components/ember/ember','把手': 'bower_components/handlebars/handlebars','jquery': 'bower_components/jquery/jquery','text': 'bower_components/requirejs-text/text'},垫片:{余烬:{deps: ['jquery', '把手'],出口:'Ember'}}});定义(功能(需要){var Ember = require('ember'),EmberAccordionComponent = require('src/EmberAccordionComponent'),EmberAccordionTemplate = require('text!templates/ember-accordion.hbs'),EmberAccordionHeaderTemplate = require('text!templates/ember-accordion-header.hbs'),EmberAccordionBodyTemplate = require('text!templates/ember-accordion-body.hbs'),ApplicationTemplate = require('text!templates/application.hbs'),IndexTemplate = require('text!templates/index.hbs');var App = Ember.Application.create({LOG_STACKTRACE_ON_DEPRECATION : 真,LOG_BINDINGS : 真,LOG_TRANSITIONS : 真,LOG_TRANSITIONS_INTERNAL : 真,LOG_VIEW_LOOKUPS : 真,LOG_ACTIVE_GENERATION : 真});Ember.TEMPLATES = {};Ember.TEMPLATES['application'] = Ember.Handlebars.compile(ApplicationTemplate);Ember.TEMPLATES['index'] = Ember.Handlebars.compile(IndexTemplate);Ember.TEMPLATES['components/ember-accordion'] = Ember.Handlebars.compile(EmberAccordionTemplate);Ember.TEMPLATES['components/ember-accordion-header'] = Ember.Handlebars.compile(EmberAccordionHeaderTemplate);Ember.TEMPLATES['components/ember-accordion-body'] = Ember.Handlebars.compile(EmberAccordionBodyTemplate);App.EmberAccordionComponent = EmberAccordionComponent;App.IndexRoute = Ember.Route.extend({模型:函数(){返回 [{名称:'鲍勃'},{名称:'吉尔'}]}})});

EmberAccordionComponent.js

define(function(require) {要求('余烬');var EmberAccordionComponent = Ember.Component.extend({});返回 EmberAccordionComponent;});

application.hbs

{{outlet}}

ember-accordion-header.hbs

{{屈服}}

ember-accordion-body.hbs

{{屈服}}

index.hbs

{{#ember-accordion listOfAccordionPaneObjects=model}}{{#ember-accordion-header}}{{记录 this.constructor}}{{记录这个}}标题 {{accordionPaneObject.name}}{{/ember-accordion-header}}{{#ember-accordion-body}}正文 {{accordionPaneObject.name}}{{/ember-accordion-body}}{{/ember-accordion}}

ember-accordion.hbs

{{#each AccordionPaneObject in listOfAccordionPaneObjects}}{{屈服}}{{/每个}}

--

这很难调试.所以放入:

{{log this.constructor}}

和:

{{log this}}

进入:

{{#ember-accordion-header}}

输出以下内容:

  • Class.model = 未定义(为什么?)
  • Ember.ArrayController

我已经尝试按照本文的建议覆盖 Ember.Component 的私有 _yield 方法( http://www.thesoftwaresimpleton.com/blog/2013/11/21/component-block/ ):

var EmberAccordionHeaderComponent = Ember.Component.extend({_yield:函数(上下文,选项){var get = Ember.get,视图 = options.data.view,parentView = this._parentView,template = get(this, '模板');如果(模板){Ember.assert("组件必须有父视图才能产生.", parentView);view.appendChild(Ember.View, {isVirtual: 真,标签名称: '',_contextView:父视图,模板:模板,context: get(view, 'context'),//默认为 get(parentView, 'context'),controller: get(view, 'controller'),//默认为 get(parentView, 'context'),模板数据:{ 关键字:parentView.cloneKeywords() }});}}});

但是当我这样做时,我仍然无法访问我的子组件范围内的 AccordionPaneObject,并且我的 {{log this.constructor}} 现在指向:.EmberAccordionHeaderComponent

所以看起来我正在到达某个地方,我只需要再上一层.

当我在 EmberAccordionHeaderComponent.js 中尝试使用此代码时:

var EmberAccordionHeaderComponent = Ember.Component.extend({_yield:函数(上下文,选项){var get = Ember.get,视图 = options.data.view,parentView = this._parentView,GrandParentView = this._parentView._parentView,template = get(this, '模板');如果(模板){Ember.assert("组件必须有父视图才能产生.", parentView);view.appendChild(Ember.View, {isVirtual: 真,标签名称: '',_contextView:父视图,模板:模板,context: get(grandParentView, 'context'),//默认为 get(parentView, 'context'),controller: get(grandParentView, 'controller'),//默认为 get(parentView, 'context'),模板数据:{ 关键字:parentView.cloneKeywords() }});}}});

我仍然无法访问accordionPaneObject,但现在我看到{{log this.constructor}} 输出.EmberAccordionComponent.所以看起来我在正确的范围内,但数据仍然没有绑定.

有趣的是,如果我在覆盖的 _yield 中使用任何这些重新分配上下文和控制器的变体,我可以在控制台中使用以下方法访问我想要的数据:

this._parentView._context.content

解决方案

我用一些评论更新了你的代码,请查看 http://emberjs.jsbin.com/ivOyiZa/1/edit.

Javascript

App = Ember.Application.create();App.IndexRoute = Ember.Route.extend({模型:函数(){返回 [{ head: "foo head", body: "foo body" },{ head: "bar head", body: "bar body" },{头:你的头",身体:你的身体"}];}});App.EmberAccordionComponent = Ember.Component.extend({//每个手风琴标题/正文项目,将有一个该视图的实例.//这样我们就可以隔离每个手风琴标题/正文的展开状态emberAccordionItemView: Ember.View.extend({展开:假}),_yield:函数(上下文,选项){var get = Ember.get,视图 = options.data.view,parentView = this._parentView,template = get(this, '模板');如果(模板){Ember.assert("组件必须有父视图才能产生.", parentView);view.appendChild(Ember.View, {isVirtual: 真,标签名称: '',_contextView:父视图,模板:模板,context: get(view, 'context'),//默认为 get(parentView, 'context'),controller: get(view, 'controller'),//默认为 get(parentView, 'context'),模板数据:{ 关键字:parentView.cloneKeywords() }});}}});App.EmberAccordionHeaderComponent = Ember.Component.extend({classNames: ['ember-accordion-header'],点击:函数(){//这里我们切换 emberAccordionItemView.expanded 属性this.toggleProperty('parentView.expanded');}});

模板

 <script type="text/x-handlebars" data-template-name="components/ember-accordion">{{#each listOfAccordionPaneObjects itemViewClass="view.emberAccordionItemView"}}<div class="ember-accordion-container"><div class="ember-accordion-pane">{{屈服}}

{{/每个}}<script type="text/x-handlebars" data-template-name="components/ember-accordion-header">{{屈服}}<script type="text/x-handlebars" data-template-name="components/ember-accordion-body"><!-- 当 EmberAccordionHeaderComponent.click 被调用时,扩展的属性会发生变化,内容是否可见,基于扩展的真相 -->{{#if parentView.expanded}}<div class="ember-accordion-pane-content">{{屈服}}

{{/如果}}

CSS

.ember-accordion-header {背景色:#999;颜色:#ffffff;填充:10px;边距:0;行高:14px;-webkit-border-top-left-radius: 5px;-webkit-border-top-right-radius: 5px;-moz-border-radius-topleft: 5px;-moz-border-radius-topright: 5px;边框左上角半径:5px;边框右上角半径:5px;光标:指针;文字装饰:无;font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;字体大小:14px;}.ember-手风琴容器{高度:100%;宽度:100%;}.ember-手风琴窗格{填充:2px;}.emberaccordionheaderselected {背景颜色:#bbb;颜色:#333;字体粗细:粗体;}.ember-accordion-header:悬停{文字装饰:下划线!重要;}.emberaccordionheaderselected:hover {文字装饰:下划线!重要;}.ember-accordion-pane-content {填充:5px;溢出-y:自动;左边框:1px 实心 #bbb;右边框:1px 实心 #bbb;边框底部:1px 实心 #bbb;-webkit-border-bottom-left-radius: 5px;-webkit-border-bottom-right-radius: 5px;-moz-border-radius-bottomleft: 5px;-moz-border-radius-bottomright: 5px;边框左下角半径:5px;边框右下角半径:5px;}.emberdisabledpane {不透明度:.2;}

I'm curious if this is even possible in ember. This is an easy thing to do in angular ( plunkr: http://plnkr.co/edit/O2e0ukyXdKMs4FcgKGmX?p=preview ):

The goal is to make an easy to use, generic, reusable accordion api for api consumers.

The api I want the caller to be able to use is this (just like the angular api):

{{#ember-accordion listOfAccordionPaneObjects=model}}

  {{#ember-accordion-heading}}
     heading template html {{accordionPaneObject.firstName}}
  {{/ember-accordion-heading}}

  {{#ember-accordion-body}}
     this is the accordion body  {{accordionPaneObject.lastName}}
  {{/ember-accordion-body}}

{{/ember-accordion}}

Here is a working example I wrote using angular:

<!doctype html>
<html ng-app="angular-accordion">
<head>
    <style>
        .angular-accordion-header {
            background-color: #999;
            color: #ffffff;
            padding: 10px;
            margin: 0;
            line-height: 14px;
            -webkit-border-top-left-radius: 5px;
            -webkit-border-top-right-radius: 5px;
            -moz-border-radius-topleft: 5px;
            -moz-border-radius-topright: 5px;
            border-top-left-radius: 5px;
            border-top-right-radius: 5px;
            cursor: pointer;
            text-decoration: none;
            font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            font-size: 14px;
        }

        .angular-accordion-container {
            height: 100%;
            width: 100%;
        }

        .angular-accordion-pane {
            padding: 2px;
        }

        .angularaccordionheaderselected {
            background-color: #bbb;
            color: #333;
            font-weight: bold;
        }

        .angular-accordion-header:hover {
            text-decoration: underline !important;
        }

        .angularaccordionheaderselected:hover {
            text-decoration: underline !important;
        }

        .angular-accordion-pane-content {
            padding: 5px;
            overflow-y: auto;
            border-left: 1px solid #bbb;
            border-right: 1px solid #bbb;
            border-bottom: 1px solid #bbb;
            -webkit-border-bottom-left-radius: 5px;
            -webkit-border-bottom-right-radius: 5px;
            -moz-border-radius-bottomleft: 5px;
            -moz-border-radius-bottomright: 5px;
            border-bottom-left-radius: 5px;
            border-bottom-right-radius: 5px;
        }

        .angulardisabledpane {
            opacity: .2;
        }
    </style>
</head>
<body style="margin: 0;">


<div style="height: 90%; width: 100%; margin: 0;" ng-controller="outerController">

    <angular-accordion list-of-accordion-pane-objects="outerControllerData">
        <pane>
            <pane-header>Header {{accordionPaneObject}}</pane-header>
            <pane-content>Content {{accordionPaneObject}}</pane-content>
        </pane>
    </angular-accordion>

</div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.js"></script>
    <script>
        angular.module('angular-accordion', [])
                .directive('angularAccordion', function() {
                    var template = '';

                    return {
                        restrict: 'E',
                        transclude: true,
                        replace: true,
                        template: '<div>' +
                                        '<div ng-transclude class="angular-accordion-container" ng-repeat="accordionPaneObject in listOfAccordionPaneObjects"></div>' +
                                  '</div>',
                        controller: ['$scope', function($scope) {
                            var panes = [];

                            this.addPane = function(pane) {
                                panes.push(pane);
                            };
                        }],
                        scope: {
                            listOfAccordionPaneObjects: '='
                        }
                    };
                })
                .directive('pane', function() {
                    return {
                        restrict: 'E',
                        transclude: true,
                        replace: true,
                        template: '<div ng-transclude class="angular-accordion-pane"></div>'
                    };
                })
                .directive('paneHeader', function() {
                    return {
                        restrict: 'E',
                        require: '^angularAccordion',
                        transclude: true,
                        replace: true,
                        link: function(scope, iElement, iAttrs, controller) {
                            controller.addPane(scope);

                            scope.toggle = function() {
                                scope.expanded = !scope.expanded;
                            };
                        },
                        template: '<div ng-transclude class="angular-accordion-header" ng-click="toggle()"></div>'
                    };
                })
                .directive('paneContent', function() {
                    return {
                        restrict: 'EA',
                        require: '^paneHeader',
                        transclude: true,
                        replace: true,
                        template: '<div ng-transclude class="angular-accordion-pane-content" ng-show="expanded"></div>'
                    };
                })
                .controller('outerController', ['$scope', function($scope) {
                    $scope.outerControllerData = [1, 2, 3];
                }]);
    </script>
</body>
</html>

here's where I'm stuck doing the same with ember:

index.html

<!DOCTYPE html>
<html>
    <body>
        <script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.9/require.js" data-main="main.js"></script>
    </body>
</html>

main.js

require.config({
    paths: {
        'ember': 'bower_components/ember/ember',
        'handlebars': 'bower_components/handlebars/handlebars',
        'jquery': 'bower_components/jquery/jquery',
        'text': 'bower_components/requirejs-text/text'
    },
    shim: {
        ember: {
            deps: ['jquery', 'handlebars'],
            exports: 'Ember'
        }
    }
});

define(function(require) {
    var Ember = require('ember'),
        EmberAccordionComponent = require('src/EmberAccordionComponent'),
        EmberAccordionTemplate = require('text!templates/ember-accordion.hbs'),
        EmberAccordionHeaderTemplate = require('text!templates/ember-accordion-header.hbs'),
        EmberAccordionBodyTemplate = require('text!templates/ember-accordion-body.hbs'),
        ApplicationTemplate = require('text!templates/application.hbs'),
        IndexTemplate = require('text!templates/index.hbs');

    var App = Ember.Application.create({
        LOG_STACKTRACE_ON_DEPRECATION : true,
        LOG_BINDINGS                  : true,
        LOG_TRANSITIONS               : true,
        LOG_TRANSITIONS_INTERNAL      : true,
        LOG_VIEW_LOOKUPS              : true,
        LOG_ACTIVE_GENERATION         : true
    });

    Ember.TEMPLATES = {};
    Ember.TEMPLATES['application'] = Ember.Handlebars.compile(ApplicationTemplate);
    Ember.TEMPLATES['index'] = Ember.Handlebars.compile(IndexTemplate);
    Ember.TEMPLATES['components/ember-accordion'] = Ember.Handlebars.compile(EmberAccordionTemplate);
    Ember.TEMPLATES['components/ember-accordion-header'] = Ember.Handlebars.compile(EmberAccordionHeaderTemplate);
    Ember.TEMPLATES['components/ember-accordion-body'] = Ember.Handlebars.compile(EmberAccordionBodyTemplate);

    App.EmberAccordionComponent = EmberAccordionComponent;

    App.IndexRoute = Ember.Route.extend({
        model: function() {
            return [
                {
                    name: 'Bob'
                },
                {
                    name: 'Jill'
                }]
        }
    })
});

EmberAccordionComponent.js

define(function(require) {
    require('ember');

    var EmberAccordionComponent = Ember.Component.extend({});

    return EmberAccordionComponent;
});

application.hbs

{{outlet}}

ember-accordion-header.hbs

<div style="color: blue;">
    {{yield}}
</div>

ember-accordion-body.hbs

<div style="color: green;">
    {{yield}}
</div>

index.hbs

{{#ember-accordion listOfAccordionPaneObjects=model}}
    {{#ember-accordion-header}}
        {{log this.constructor}}
        {{log this}}
        Header {{accordionPaneObject.name}}
    {{/ember-accordion-header}}
    {{#ember-accordion-body}}
        Body {{accordionPaneObject.name}}
    {{/ember-accordion-body}}
{{/ember-accordion}}

ember-accordion.hbs

{{#each accordionPaneObject in listOfAccordionPaneObjects}}
    {{yield}}
{{/each}}

--

This is tricky to debug. So putting in the:

{{log this.constructor}}

and the:

{{log this}}

into the:

{{#ember-accordion-header}}

outputs the following:

  • Class.model = undefined (why?)
  • Ember.ArrayController

I've tried overriding the private _yield method of Ember.Component as suggested by this article ( http://www.thesoftwaresimpleton.com/blog/2013/11/21/component-block/ ):

var EmberAccordionHeaderComponent = Ember.Component.extend({
    _yield: function(context, options) {
        var get = Ember.get,
            view = options.data.view,
            parentView = this._parentView,
            template = get(this, 'template');

        if (template) {
            Ember.assert("A Component must have a parent view in order to yield.", parentView);
            view.appendChild(Ember.View, {
                isVirtual: true,
                tagName: '',
                _contextView: parentView,
                template: template,
                context: get(view, 'context'), // the default is get(parentView, 'context'),
                controller: get(view, 'controller'), // the default is get(parentView, 'context'),
                templateData: { keywords: parentView.cloneKeywords() }
            });
        }
    }
});

but when I do this I still don't have access to accordionPaneObject in my child component scope, and my {{log this.constructor}} now points to: .EmberAccordionHeaderComponent

So it looks like I'm getting somewhere, I just need to go one more level up.

When I try that using this code in EmberAccordionHeaderComponent.js:

var EmberAccordionHeaderComponent = Ember.Component.extend({
    _yield: function(context, options) {
        var get = Ember.get,
            view = options.data.view,
            parentView = this._parentView,
            grandParentView = this._parentView._parentView,
            template = get(this, 'template');

        if (template) {
            Ember.assert("A Component must have a parent view in order to yield.", parentView);
            view.appendChild(Ember.View, {
                isVirtual: true,
                tagName: '',
                _contextView: parentView,
                template: template,
                context: get(grandParentView, 'context'), // the default is get(parentView, 'context'),
                controller: get(grandParentView, 'controller'), // the default is get(parentView, 'context'),
                templateData: { keywords: parentView.cloneKeywords() }
            });
        }
    }
});

I still don't access to accordionPaneObject in, but now I see {{log this.constructor}} outputting .EmberAccordionComponent. So it appears I'm in the right scope, but the data still doesn't bind.

Interestingly enough, if I use any of these variations of reassigning context and controller in my overridden _yield, I can access the data I am after in the console using:

this._parentView._context.content

解决方案

I updated your code with some comments please give a look http://emberjs.jsbin.com/ivOyiZa/1/edit.

Javascript

App = Ember.Application.create();

App.IndexRoute = Ember.Route.extend({
  model: function() {
    return [
      { head: "foo head", body: "foo body " },
      { head: "bar head", body: "bar body " },
      { head: "ya head", body: "yo body " }
    ];
  }
});

App.EmberAccordionComponent = Ember.Component.extend({
  // each accordion header/body item, will have a instance of that view.
  // so we can isolate the expanded state for each accordion header/body
  emberAccordionItemView: Ember.View.extend({    
    expanded: false
  }),
  _yield: function(context, options) {
    var get = Ember.get, 
    view = options.data.view,
    parentView = this._parentView,
    template = get(this, 'template');

    if (template) {
      Ember.assert("A Component must have a parent view in order to yield.", parentView);      
      view.appendChild(Ember.View, {
        isVirtual: true,
        tagName: '',
        _contextView: parentView,
        template: template,
        context: get(view, 'context'), // the default is get(parentView, 'context'),
        controller: get(view, 'controller'), // the default is get(parentView, 'context'),
        templateData: { keywords: parentView.cloneKeywords() }
      });
    }
  }
});

App.EmberAccordionHeaderComponent = Ember.Component.extend({  
  classNames: ['ember-accordion-header'],  
  click: function() {
    // here we toggle the emberAccordionItemView.expanded property
    this.toggleProperty('parentView.expanded');  
  }
});

Templates

  <script type="text/x-handlebars" data-template-name="index">
    {{#ember-accordion listOfAccordionPaneObjects=model}}                        
          {{#ember-accordion-header}}
              {{head}} <!-- each object passed in listOfAccordionPaneObjects=model can be accessed here -->
          {{/ember-accordion-header}}
          {{#ember-accordion-body}}
              {{body}} <!-- each object passed in listOfAccordionPaneObjects=model can be accessed here -->
          {{/ember-accordion-body}}        
    {{/ember-accordion}}        
  </script>

  <script type="text/x-handlebars" data-template-name="components/ember-accordion">     
    {{#each listOfAccordionPaneObjects itemViewClass="view.emberAccordionItemView"}}            
      <div class="ember-accordion-container">
        <div class="ember-accordion-pane">          
            {{yield}}          
        </div>
      </div>      
    {{/each}}
  </script>

  <script type="text/x-handlebars" data-template-name="components/ember-accordion-header">        
    {{yield}}    
  </script>

  <script type="text/x-handlebars" data-template-name="components/ember-accordion-body">    
    <!-- when EmberAccordionHeaderComponent.click is called, the expanded property change and the content can be visible or not, based on expanded truth -->
    {{#if parentView.expanded}}
      <div class="ember-accordion-pane-content">
        {{yield}}
      </div>
    {{/if}}
  </script>

Css

.ember-accordion-header {
  background-color: #999;
  color: #ffffff;
  padding: 10px;
  margin: 0;
  line-height: 14px;
  -webkit-border-top-left-radius: 5px;
  -webkit-border-top-right-radius: 5px;
  -moz-border-radius-topleft: 5px;
  -moz-border-radius-topright: 5px;
  border-top-left-radius: 5px;
  border-top-right-radius: 5px;
  cursor: pointer;
  text-decoration: none;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 14px;
}

.ember-accordion-container {
  height: 100%;
  width: 100%;
}

.ember-accordion-pane {
  padding: 2px;
}

.emberaccordionheaderselected {
  background-color: #bbb;
  color: #333;
  font-weight: bold;
}

.ember-accordion-header:hover {
  text-decoration: underline !important;
}

.emberaccordionheaderselected:hover {
  text-decoration: underline !important;
}

.ember-accordion-pane-content {
  padding: 5px;
  overflow-y: auto;
  border-left: 1px solid #bbb;
  border-right: 1px solid #bbb;
  border-bottom: 1px solid #bbb;
  -webkit-border-bottom-left-radius: 5px;
  -webkit-border-bottom-right-radius: 5px;
  -moz-border-radius-bottomleft: 5px;
  -moz-border-radius-bottomright: 5px;
  border-bottom-left-radius: 5px;
  border-bottom-right-radius: 5px;
}

.emberdisabledpane {
  opacity: .2;
}

这篇关于如何从 ember 中的子组件范围访问父组件范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆