是否可以通过模板将父组件的属性绑定到子组件计算属性?

时间:2015-02-17 14:01:03

标签: ember.js

是否可以通过模板将父组件的属性绑定到子组件计算属性?

目标是通过绑定访问子组件的计算属性。

// We are in some parent component's template
{{child-component aComputedProp=aNonComputedProp}}

// Parent component
export default Ember.Component.extend({
  aNonComputedProp: null
});

// Child component
export default Ember.Component.extend({
  aComputedProp: function () {
    return 4 + 4;
  }.property()
});

更新

@KalmanKalman Hazins

虽然这种方法在对该子组件执行操作时效果很好,但当祖先组件需要访问该子组件的数据时,该方法将无效。

这是描述困境的图像。

enter image description here

我能想到让组件彼此通信而没有硬依赖性的唯一方法是通过服务(或充当服务的父组件),以及伪装的API的一系列触发器/处理程序事件

更新

我想的另一种方法是通过以下方式从ChildComponent1装饰父控制器:

  decorateTargetObject: function () {
    Ember.defineProperty(this.get('targetObject'), 'height', Ember.computed(function () {
      return this.$().outerHeight();
    }.bind(this)));
  }.on('init')

ChildComponent2可以通过this.get('targetObject.height')

访问该属性

当然,这会破坏单向封装,因为组件需要浸入其控制器中。

没有办法将现有属性设置为计算属性而不重新定义它(没有Ember.defineProperty)?

//In ChildComponent1
decorateTargetObject: function () {
  this.set('targetObject.height', ...a computed function...)
}.on('init')

1 个答案:

答案 0 :(得分:0)

这是不可能的(直接通过模板),但这就是你要做的:)(而不是)。

您可以向父级发送操作,并将值传递给更改。然后,在父操作中,您可以更新值。

App.XParentComponent = Ember.Component.extend({
  helloParent: null,

  actions: {
    updateHelloParent: function(value){
      this.set('helloParent', value);
    }
  }
});

App.XChildComponent = Ember.Component.extend({
  helloName: function(){
    var name = this.get('name');
    var helloName = '';
    if(name) {
      var helloName = "Hello " + name;
    }

    this.sendAction('action', helloName);

    return helloName;      
  }.property('name')
});

您的模板如下所示:

<script type="text/x-handlebars" id="components/x-parent">
  <h2>Parent</h2>

  {{ helloParent }}

  {{ x-child action="updateHelloParent"}}
</script>

<script type="text/x-handlebars" id="components/x-child">
  <h2>Child</h2>

  {{ input value=name }} <p/> 

  {{ helloName }}
</script>

工作解决方案here

<强>更新

根据docs,您可以针对您的用例执行以下操作:

App.HeightController = Ember.Controller.extend({
  height: 0
});

App.IndexController = Ember.Controller.extend({
  needs: ['height'],
  height: Ember.computed.alias('controllers.height.height')
});

App.XChild1Component = Ember.Component.extend({
  heightDidChange: function(){
    var val = this.get('val');
    if(val) {
      this.set('height', parseInt(val));  
    }    
  }.observes('val')
});

然后,在您的模板中,您可以拥有以下内容:

<script type="text/x-handlebars" data-template-name="index">
  Height(index): {{ height }} <p/>
  {{ x-parent height=height}}
</script>

<script type="text/x-handlebars" id="components/x-parent">
  <h2>Parent</h2>

  Height(parent): {{ height }} <p/>

  {{ x-child1 height=height}}

  {{ x-child2 height=height}}
</script>

<script type="text/x-handlebars" id="components/x-child1">
  <h2>Child 1</h2>

  Height(child1): {{ height }} <p/>
  {{ input value=val placeholder='Type new heght here...'}} <p/> 

</script>

<script type="text/x-handlebars" id="components/x-child2">
  <h2>Child 2</h2>

  Height(child2): {{ height }} <p/>    
</script>

更新了解决方案here