2016-06-11 10 views
10

Próbuję przełączać menu nawigacji po stronie, znajdujące się u góry głównego szablonu aplikacji, za pomocą przycisku w zagnieżdżonym komponencie potomnym. Nie mogę wymyślić, jak dostać się do komponentu sidenav w rodzica, aby powiedzieć to do sidenav.open().Dostęp do elementu nadrzędnego @Component i zmiennych z komponentu * Routed * Child Komponent

Wiem o @Input i @Output na składniku podrzędnym, ale jak rozumiem, do korzystania z tego muszę mieć jakiś tag DOM dla elementu podrzędnego, aby dołączyć je do? Takich jak:

<app> 
    <sidenav-component #sidenav>...</sidenav-component> 

    <child [someInput]="some_parent_var" (childOpensNav)="sidenav.open()"></child> 
</app> 

Mnóstwo artykułów o tym, jak to zrobić. Problem polega na tym, że jestem routing do tego składnika, więc nie istnieje znaczek <child> w kodzie. Raczej mój kod jest tak:

<app> 
    <sidenav-component #sidenav>...</sidenav-component> 

    <router-outlet></router-outlet> 
</app> 

Jeśli mam element podrzędny, który kierowany jest do, jak mogę zrobić sidenav.open() lub w jakiś sposób uzyskać dostęp do komponentu w rodzica z dzieckiem?

Kilka myśli: Zrobiłem kilka badań i zastanawiałem się nad kilkoma podejściami i nie jestem pewien, czy są poprawne, czy nawet działają ... Jednym ze sposobów korzystania z usługi wtryskiwacza i próby przejścia do rodzica, ale czuje się źle:

// child component 
constructor(injector: Injector) { 
    this.something = injector.parent.get(Something); 
} 

ewentualnie stworzenie usługi na rodzica, jakoś przymocowany do elementu Sidenav a następnie wstrzykując tę ​​usługę do dziecka ??

+0

To jest dosłownie to, co próbuję zrobić. Nie mogę uwierzyć, że znalazłem twoje pytanie. Dzięki. Mam nadzieję, że przejdę w dół i otrzymam dobrą odpowiedź. – krummens

Odpowiedz

9

Najprostszym i najczystszym sposobem jest wykorzystanie usługi.

Usługa jak mogłoby to wyglądać tak:

export class DomService { 
    sidebarVisible: boolean = true; 

    showSidebar() { 
     sidebarVisible = true; 
    } 

    hideSidebar() { 
     sidebarVisible = false; 
    } 

    toggleSidebar() { 
     sidebarVisible = !sidebarVisible; 
    } 
} 

w wywołaniu bootstrap dodać usługę do listy dostawców:

bootstrap(App, [ 
    // other providers 
    DomService 
]); 

W składników (być może w app.ts ale także w swojej sidenav.ts) gdzie chcesz pokazać/ukryć pasek boczny dodaj usługę do wstrzyknięcia:

constructor(private _domService: DomService) { 

} 

W szablonie, w którym chcesz, aby włączyć/pokaż/ukryj można teraz zrobić:

<sidenav-component *ngIf="_domService.sidebarVisible">...</sidenav-component> 

<div id="toggle-sidebar" (click)="_domService.toggleSidebar()">toggle</div> 
+2

Intersting i dziękuję. Wypróbuję to wkrótce.Jest jednak sprzeczne z intuicją, aby stworzyć usługę dostępu do elementów DOM, gdy dostępny jest "@ ViewChild", wydaje się, że Angular 2 może zapewnić coś w stylu '@ ViewParent' lub coś, co uczyni go bardziej intuicyjnym? Damy ci znać, jak mi idzie. Ponadto, jak dostałeś się do tej odpowiedzi/dowiedziałeś się, że jest to "najlepsza praktyka"? Dzięki! – FireDragon

+0

Zasadniczo można to zrobić za pomocą [właściwości wejściowych i wyjściowych] (https://angular.io/docs/ts/latest/guide/template-syntax.html#!#input-and-output-properties) na swoim 'sidenav-component' tag, ale jeśli potrzebujesz go z kilku innych miejsc, stanie się naprawdę brudny. – rinukkusu

0

Lubię zaakceptowane odpowiedź, wydaje się bardziej solidny kątowa sposób to zrobić prawidłowo (zwłaszcza jeśli masz zamiar dodawać więcej opcji).

Chciałem jednak uzyskać szybki, brudny dostęp do elementu globalnego według identyfikatora. Wszyscy mówią o użyciu @ViewChild, ale chcę chodzić w GÓRĘ drzewa. Właśnie wrócił do szkoły i używane to w metodzie komponent:

document.getElementById('nav-panel').className = 'hide'; 

Jeśli chcemy wiele kopii tej pracy (np lewe i prawe menu boczne) musimy wprowadzić coś w dół dzieci, żeby wiedzieć, które Id szukać.