Ember.js | notify other components about one component

in the component section in the Ember manuals there is a demonstration of the Summary Summary component, clicking on one Post Summery title opens its contents below it.

I would like to add functionality to simultaneously close any other open messages.

The purpose of my question is to understand how ember speaks between components without sacrificing isolation.

The solutions I was thinking of are as follows:

  • there is some shell component that somehow handles it

  • triggering an event such as "post-summery: open" and including other components on it (but then it can interact with other places in the application using the same components to use diffecnt)

this is the original demo from the documentation: http://jsbin.com/uyibis/1/edit

Here is how I could implement the behavior with jQuery: http://jsbin.com/eremon/2/edit

var $ contents = $ ('. content'). hide ();

$ (document) .on ('click', '.title', function () {

$ contents.hide ();
$ (This) .next ('content'.) Show () ;.

});

enter image description here

+4
source share
2 answers

With Ember.Component you don't have a childViews control, so I used Ember.CollectionView to control the elements. Since App.PostSummaryComponent already extends Ember.Component , I delegate Ember.CollectionView behavior using view containerViewClass in the template. So, we have the best of two worlds.

Since this containerViewClass property is a class, we need a way to access this instance β€” to interact with childViews β€” when creating the view. To do this, you need to use viewName='containerView' in the template. This tells Ember that a new instance of containerViewClass will be set in the containerView property. Therefore we can use this.get("containerView") in App.PostSummaryComponent .

The last change was to move each helper from the index template to the component template. So other calls to the component do not need to be repeated.

http://jsbin.com/ebayip/2/edit

+2
source

This problem occurs constantly in Ember. The way I solve this is to keep track of which publication is β€œopen” on the controller, and then each element should be responsible for its own state based on this data. This way, you do not need to manually reset each state of the message every time you switch it.

The canonical source of truth is the controller.

 App.IndexController = Ember.ArrayController.extend({ content: null, selectedPost: null // null means no post selected }); 

We pass this information to the components through the template.

 <script type="text/x-handlebars" data-template-name="index"> {{#each post in controller}} {{post-summary post=post selectedPost=selectedPost}} {{/each}} </script> <script type="text/x-handlebars" id="components/post-summary"> <h3 {{action "toggleBody"}}>{{post.title}}</h3> {{#if isShowingBody}} <p>{{{post.body}}}</p> {{/if}} </script> 

Now body visibility for a given message can be calculated using the property.

 App.PostSummaryComponent = Ember.Component.extend({ post: null, selectedPost: null, isShowingBody: function() { return this.get('selectedPost') === this.get('post'); }.property('selectedPost', 'post'), toggleBody: function() { this.set('selectedPost', this.get('isShowingBody') ? null : this.get('post')); } }); 

Here's the jsfiddle .

It can be argued that this is not an ideal object-oriented solution, but it has significantly improved the structure and support of my Ember applications. You can implement a wide range of complex list behavior, since each element is responsible for its own state based on a common source of truth.

+5
source

Source: https://habr.com/ru/post/1495124/


All Articles