3

I have a <navbar> component, which has a method makeSelected, which as the name says makes an item selected. This works great while clicking on the item, however on my homepage, i want it to be selected without having to click it.

I've injected the Navbar component into my Home component, and in the Home constructor i call the makeSelected method:

import {Component, View} from 'angular2/core';
import {Navbar} from '/app/navbar/navbar';

@Component({
  selector: 'home',
  providers: [Navbar]
})

@View({
  templateUrl: '/app/home/home.html',
  directives: [Navbar]
})

export class Home {

    constructor(public navbar : Navbar) {

      this.navbar = navbar;
      this.navbar.makeSelected('Item 1');

    }

}

The navbar component:

import {Component, View} from 'angular2/core';

@Component({
  selector: 'navbar'
})

@View({
  template: `
  <ul>
    <li *ngFor="#item of items; #i = index" (click)="makeSelected(item.name)">

      {{ item.name }} <div *ngIf=" item.selected == true"> [selected] </div>

    </li>
  </ul>
  `
})

export class Navbar{
  constructor(){
      this.items = [
        {id: 1, name: 'Item 1', href: 'http://www.google.com', selected: false}
      ]
  }
  makeSelected(name)
  {
    for(var i in this.items)
    {
      this.items[i].selected = false;

      if(this.items[i].name == name)
      {
        this.items[i].selected = true;
      }
    }
  }
}

The page displays fine, but the item is not selected. There are no errors, so the method seems to be called.

Why isn't the item selected?

David Ericsson
  • 2,260
  • 2
  • 15
  • 31

1 Answers1

1

You can't inject child components like this into the parent component. You should reference this component using @ViewChild or @Query:

export class Home {
  constructor(@Query(Navbar) children:QueryList<Navbar>) {
    this.navbar = children.first();
    this.navbar.makeSelected('Item 1');
  }
}

Be careful to remove NavBar from the providers property of the component. Keep it only in the directives property.

See this question for more details:

Community
  • 1
  • 1
Thierry Templier
  • 182,931
  • 35
  • 372
  • 339
  • parent `Component` is accessing `Child` component? is it cool way? – Pankaj Parkar Feb 22 '16 at 22:30
  • 2
    @PankajParkar, yes, that's fine. It's the other direction that should be rare: see Miško's first comment on this thread: https://github.com/angular/angular/issues/3216, and the [related question](http://stackoverflow.com/questions/34540615/how-do-i-inject-a-parent-component-into-a-child-component) – Mark Rajcok Feb 22 '16 at 22:39
  • Thanks! I've managed to do it with `@ViewChild` https://angular.io/docs/js/latest/api/core/ViewChild-var.html – David Ericsson Feb 22 '16 at 23:02
  • @MarkRajcok Thanks for clearing that out.. but doesn't it look like creating a sharable service would be good option here..? Suppose I will have `NavbarService` in a place which will have `items`(`NavbarService` will inject to bootstrap to make sure its instance should create once only) and `makeSelected` method will be there in `NavbarService`, `Navbar` & `Home` component take(singleton) instance of `NavbarService`.. or am I missed something conceptually? – Pankaj Parkar Feb 23 '16 at 07:13
  • Pankaj, this sounds better to me. I'll give that a try. Thank you – David Ericsson Feb 23 '16 at 08:26
  • 1
    Thanks Pankaj and Mark for your comments! – Thierry Templier Feb 23 '16 at 08:43
  • 2
    @PankajParkar, yes a Navbar component and an associated NavbarService sounds like a good solution. Here's [an answer](http://stackoverflow.com/questions/34376854/delegation-eventemitter-or-observable-in-angular2/35568924#35568924) I just wrote last night for a NavService with an Observable that could be applicable here. – Mark Rajcok Feb 23 '16 at 15:39