Martin
Martin

Reputation: 24308

ui-router: named views (multiple) views, keeping everything decoupled?

I have just started out with ui-router and I am creating components (angular 1.5) and using the new component method explained here, although it shouldn't matter - http://angular-ui.github.io/ui-router/1.0.0-alpha.5/interfaces/ng1.ng1viewdeclaration.html#component

I think I need to be looking at absolute and relative views for my states. Let me paint the picture for my issue, probably better with an explanation.

I have a number of high level components (using angular 1.5 components). Some of the high level components have child components but I didn't want to tightly couple these things together.

So taking an example of a search component, inside this search component it is dependent on a history item and a saved items. Both history items and saved items are child components. Saved items also has 2 children: cloud items and local items.

So in the search component I didn't want to tightly couple it to the child components because I can use the search component without the children, so I thought about using the relative view.

I could place 2 x

<div ui-view></div>

in search component and 2 x

<div ui-view></div>

in saved items.

But it just feels wrong, I am not specifically tightly coupling with specific view names but still search component expects 2 children and saved items would expect 2 also, this may not be the case.

Maybe I am overthinking it and making my components too small ? But I wanted them to be better composeable and technically the search can exist without its children.

Upvotes: 4

Views: 496

Answers (4)

Cosmin Ababei
Cosmin Ababei

Reputation: 7072

I would stay away from using any views inside your search component. Otherwise, you'll force its consumers to know about its states in order to activate its 2 children.

I have the impression you're overthinking it. As long as its children are specific, meaning that they aren't used anywhere else, I don't see anything wrong in explicitly declaring them inside their parent component.

Upvotes: 1

mfrachet
mfrachet

Reputation: 8922

I may not understand your problem, but from what I've got, you can have an intermediate component that could act as an abstraction layer.

If your component are not really tightly coupled (and it seems to be the case concerning your search component and your history), you can simply make something like that in your "higher level component"

<!-- We're inside an higher component with some data initialization -->
<!-- passing data by references, this way both component use the same data -->
<search-cmpt search-terms="searchTermsFromHigher"/>
<history filter-terms="searchTermsFromHigher"/>
<div ui-router></div> <!-- in which you resolve another component not tightly coupled -->

The key problem here, in my sense, is not how to organize your components, but how you can pass data between them. Am I right ? If it's the case, you may think about managing your frontend state differently that you're actually doing.

NB : It's possible that I didn't get the question correctly.

Upvotes: 1

Rusty
Rusty

Reputation: 329

One way to do it (if I understood the question correctly), even though it may feel like a workaround, would be to create multiple components that share a lot of the same logic.

var setup = {
  controller: searchController,
  bindings: {
    a: '=',
    b: '<',
    c: '@'
  }
};

angular.module('app')
  .component('search', angular.extend(setup, {
    templateUrl: 'search.html'
  }))
  .component('searchWithChildren', angular.extend(setup, {
    templateUrl: 'search-with-children.html'
  }));

var searchController() {
  ...

Upvotes: 1

Pushpendra
Pushpendra

Reputation: 1712

If I have understood your question correctly, what you may want to do is restrict your parent component directive as an Element restrict:'E' and add child components as an attribute to this directive restrict them as an attribute restrict:'A'

and use directives in directives and linking function to handle child directives

So your final directive should look something like this

<ui-view newattr1 newattr2></ui-view>

where ui-view will be your parent component and newattr1, newattr2 will be child components. If you don't have either of the child component in your <ui-view newattr1 newattr2></ui-view> respective linking function of child component.

Upvotes: 2

Related Questions