1

I’d appreciate if you could share you view/experience.

Suppose you have a view which contains several widgets that share some of the data (fetched from a server). For example we might have a tree, list and breadcrumbs widgets in the same view, naturally a name of a single item can be displayed in more than one widget at the same time. My question is what is the best practice of developing such views? Specifically:

  1. Are the widgets totally independent? (The easiest to implement, but suffer from performance problems)
  2. If the widgets are dependent, do they communicate through:
    1. A single model (introduces tight coupling between widgets and prevents further code evolution)
    2. Events (lose coupling but error-prone due to lose contract, less explicit code)
    3. Any other way
  3. Provided those widgets have their own controllers and scopes, how do you propagate the change notifications from the URL (or any other event) to all of them? For example if you wanna see an entity with a specific ID using URL routing, do you have a top-most view controller that is responsible to catch this change and notify all the widgets about it using some in-house mechanism, or do the widgets catch the event independently?

I guess all these questions are somehow related so feel free to answer them in whatever form/order you like.

Thanks.

Stas
  • 1,059
  • 2
  • 16
  • 26

1 Answers1

3

Are the widgets totally independent?

I think that is too broad of a question for us to answer, as that really depends on what the widgets/directives are doing. Are you asking if they should be using isolate scopes? See also When writing a directive in AngularJS, how do I decide if I need no new scope, a new child scope, or a new isolated scope?

do they communicate through...

Again, too broad, sorry... it depends on what the directives do. Besides the ways you already listed, you could also communicate via

  • a service, which is probably what I'd use if I had more than two directives that needed to communicate
  • require: 'controllerNameHere'. With the require approach, you would define methods on your controllers using this instead of $scope. This method is limited to essentially one-way communication though: from the directive that has require to the directive that it is requiring. E.g., on the AngularJS home page, the pane directive requires the tabs directive. This allows the pane directive to call methods on the tabs directive's controller, but the tabs directive can not call methods on the pane directive's controller. (For more on this, see 'this' vs $scope in AngularJS controllers)

how do you propagate the change notifications

That depends on the type of scopes your directives have. If you are using scope: true for your directives, you don't have to propagate anything. They can all $watch some parent scope property (and because of the way JavaScript prototypal inheritance works, all of the directives can see the parent scope properties). If you are using scope: {...}, then you can use '=' or '@' to define local directive scope variables and use $watch to watch them.

If you are concerned about performance with $watches (since they are evaluated at least once every digest cycle), then events might be more appropriate.

Another thing to consider: do you want your directives to know about URLs or just scope properties? Using scope properties would likely make your directives more reusable.

Community
  • 1
  • 1
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • Hi Mark. Thanks for the answer. By independent I mean - do they all have separate business logic that, for instance, fetches relevant data for display from the server. My concern is of course two-fold - if they are independent in this respect, they are easy to write and reuse, but since other widgets might require the same data it's a waste of network. If they depend on each other, on the other hand, they become tightly coupled and difficult to maintain. I will process your other suggestions in my head and let you know if they are applicable in our case. Thanks. – Stas Mar 18 '13 at 15:21
  • Mark, hi again. The communication using service or using the require attribute sounds a bit too coupled for me, this way the widgets lose their flexibility. Therefore I tend to use the event-based communication. Regarding the last question, indeed your proposed approach of listening to some property on the parent scope seems the best, because it reduces the dependency. As a whole, you can see I prefer developing independent widgets. – Stas Mar 19 '13 at 10:25
  • There are however people in my project that prefer to maintain shared model on the common (upper) scope, so all widgets can see the same data. This approach is much simpler from the communication perspective, so there's only one place where the data is located and all the widgets have access to it, so there no need to communicate, because basically you really look at the same data. However this introduces hard coupling, which I'm afraid becomes unmanageable once the product grows bigger and more complex and you start reusing widgets in other places. – Stas Mar 19 '13 at 10:28
  • 2
    @Stas, I would personally favor a service over a common upper scope. The common upper scope approach requires a certain HTML structure (or the use of $rootScope). I don't recommend data sharing be restricted by HTML structure. – Mark Rajcok Mar 19 '13 at 14:48