2

How to limit component events to it's parent/child components and prevent bubbling up.

I have the following two components:

ParentComponent.dart

@Component(
  selector: "parent-component",
  template: '<div>parent value: {{value}}<content></content></div>',
  useShadowDom: false
)
class ParentComponent implements ScopeAware{
  Scope _scope;

  @NgAttr('value')
  String value;

  void set scope(Scope scope){
    _scope = scope;
    _scope.on('select-child').listen((ScopeEvent event){
      value = event.data['value'];
    });
  }
}

ChildComponent.dart

@Component(
  selector: "child-component",
  template: '<div ng-click="select()">child: {{value}}</div>',
  useShadowDom: false
)
class ChildComponent implements ScopeAware{
  Scope _scope;

  @NgAttr('value')
  String value;

  void select(){
    _scope.parentScope.broadcast('select-child', {
      'value': value
    });
  }

  void set scope(Scope scope){
    _scope = scope;
  }
}

When one clicks on the child component, the parent updates its value.

But when i have more parent components they listen all to the same childs:

<!-- Parent 1 -->
<parent-component>
  <child-component value="foo"></child-component>
  <child-component value="bar"></child-component>
</parent-component>

<!-- Parent 2 -->
<parent-component>
  <child-component value="herp"></child-component>
  <child-component value="derp"></child-component>
</parent-component>

When i click the foo child-component of parent1 both parent components change their value to 'foo'.

I already tried playing with emit, broadcast. I know broadcast bubbles downwards to the leaf nodes and emit bubbles up. I also tried usind "scope.createChild()" but i think i miss something.

How can i create a scope in parent which is only visible to the child and vice versa? Or how to use broadcast emit correctly?

When i understand the docs right i have to use emit() in child-component and not parentNode.broadcast() but i can't get it to work

1 Answer 1

1

Good question. Your confusion is coming from the fact that while components do create new scopes, those scopes are only available to the shadowDom (the html in the template: annotation).

In your example all 6 components - 2 parents and 4 children, create scopes that are child scopes of root scope. So when you are calling parentScope.broadcast you are firing event from rootScope down to all 6 scopes.

The easiest way to achieve the behavior you want is to directly inject ParentComponent into ChildComponent. Parent components are injectable to components in both their light and shadow DOMs.

class ChildComponent implements ScopeAware {
  ParentComponent _p;    
  ChildComponent(this._p);
  void select(){
    _p.setValue(value);
  }
  ...
}

Only downside is that makes the two components more tightly coupled to each other, which is ok if you are authoring both for your own application.

Sign up to request clarification or add additional context in comments.

1 Comment

In angulardart-1.0 ChildComponent(this._p); gives me the following error: 'package:angular/core_dom/view_factory.dart': Failed assertion: line 53 pos 12: 'scope != null' is not true.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.