1

I have a list like to:

<ul>
<li><a class="group-active">Group 1</a>
    <ul>
        <li routerLinkActive="active"><a [routerLink]="['/group1/page1']">Group 1 - Page 1</a>
        <li routerLinkActive="active"><a [routerLink]="['/group1/page2']">Group 1 - Page 2</a>
        <li routerLinkActive="active"><a [routerLink]="['/group1/page3']">Group 1 - Page 3</a>
    </ul>
</li>
<li><a>Group 2</a>
    <ul>
        <li routerLinkActive="active"><a [routerLink]="['/group2/page1']">Group 2 - Page 1</a>
        <li routerLinkActive="active"><a [routerLink]="['/group2/page2']">Group 2 - Page 2</a>
        <li routerLinkActive="active"><a [routerLink]="['/group2/page3']">Group 2 - Page 3</a>
    </ul>
</li>
<li><a>Group 3</a>
    <ul>
        <li routerLinkActive="active"><a [routerLink]="['/group3/page1']">Group 3 - Page 1</a>
        <li routerLinkActive="active"><a [routerLink]="['/group3/page2']">Group 3 - Page 2</a>
        <li routerLinkActive="active"><a [routerLink]="['/group3/page3']">Group 3 - Page 3</a>
    </ul>
</li>
</ul>

I need: change the class "group-active" (of the first group) when i choose one of their elements. Their elements works fine, but i can't apply the style to corresponding element header.

Any idea?

Thanks

Luis
  • 2,006
  • 5
  • 31
  • 47

2 Answers2

2

That's a good question. I could see many people needing this.

Export the routerLinkActive to a template variable and then use isActive:

<li><a [class.group-active]="r1.isActive || r2.isActive || r2.isActive">Group 1</a>
    <ul>
        <li routerLinkActive="active" #r1="routerLinkActive"><a [routerLink]="['/group1/page1']" #r1="routerLinkActive">Group 1 - Page 1</a>
        <li routerLinkActive="active" #r2="routerLinkActive"><a [routerLink]="['/group1/page2']">Group 1 - Page 2</a>
        <li routerLinkActive="active" #r3="routerLinkActive"><a [routerLink]="['/group1/page3']">Group 1 - Page 3</a>
    </ul>
</li>

You could also write a simple directive that has a boolean like this:

@Directive({
   selector: '[any-active]',
   exportAs 'anyActive'
})
public class AnyActiveDirective implements DoCheck {
  @ViewChildren(RouterLinkActive)
  public links: QueryList<RouterLinkActive>;

  public active: boolean = false;

  public constructor(private cdr: ChangeDetectorRef) {
  }

  public ngDoCheck() {
     if(this.links) {
        const active = !!this.links.find((link)=>link.isActive);
        if(this.active !== active) {
            thia.active = active;
            this.cdr.markForCheck();
        }
     }
  }
}

Then in the template:

<li any-active #group1="actActive"><a [class.group-active]="group1.active">Group 1</a>
    <ul>
        <li routerLinkActive="active"><a [routerLink]="['/group1/page1']" #r1="routerLinkActive">Group 1 - Page 1</a>
        <li routerLinkActive="active"><a [routerLink]="['/group1/page2']">Group 1 - Page 2</a>
        <li routerLinkActive="active"><a [routerLink]="['/group1/page3']">Group 1 - Page 3</a>
    </ul>
</li>

You can try the first approach if your template is kind of static, but if your links are generated with a *ngFor then give the custom directive a try.

UPDATED:

I don't think my previous answer was very good. The routerLinkActive directive will set the CSS value if any children with routerLink are active.

Therefore, this should be enough to get it working:

<li><a routerLinkActive="group-active">Group 1</a>
    <ul>
        <li routerLinkActive="active"><a [routerLink]="['/group1/page1']">Group 1 - Page 1</a>
        <li routerLinkActive="active"><a [routerLink]="['/group1/page2']">Group 1 - Page 2</a>
        <li routerLinkActive="active"><a [routerLink]="['/group1/page3']">Group 1 - Page 3</a>
    </ul>
</li>
Reactgular
  • 52,335
  • 19
  • 158
  • 208
  • Thank you for your answer. I think your code i can using it in another similar case. – Luis Jul 07 '17 at 17:06
  • https://stackoverflow.com/questions/44976194/angular-2-4-ngstyle-apply-different-style-depeding-its-father-element-active – Luis Jul 07 '17 at 17:08
1

Well, I found my solution and i share it with you. Angular is very smart. Just I need to add the same routerLinkActive in the corresponding element:

<li><a routerLinkActive="group-active">Group 1</a>
...
<li><a routerLinkActive="group-active">Group 2</a>
...
<li><a routerLinkActive="group-active">Group 3</a>
...

I hope it helps someone else.

Luis
  • 2,006
  • 5
  • 31
  • 47