2017-12-26 2 views
1

Kurz gesagt, ich habe eine Angular 4 App, die eine Kopfzeile mit einem Android inspiriert Floating-Aktion hat, wenn diese Schaltfläche eine Methode auf die derzeit aktive Komponente ausgeführt werden soll (der Seiteninhalt grundsätzlich). Ich benutze den eckigen 4-Router, wenn das einen Unterschied macht. Es hat einige Bedenken mit dem View-Kind-Ansatz aufgeworfen, weil ich nicht immer sicher bin, welche Komponente momentan aktiv ist und wenn möglich, würde ich vermeiden, jedem einen #binding hinzuzufügen einzelne Vorlage.Angular 4 - Aufruf der Kind-Komponente Methode aus der App-Komponente

Ich habe dies von ViewChild Dekorateure, ContentChild Dekorateure, Veranstaltungen, Dienstleistungen versucht, Bisher absolut nichts hat funktioniert und ich bin flach stecken. An diesem Punkt bin ich mir nicht sicher, ob das wirklich kompliziert ist oder nur PEBCAK.

Die Schaltfläche in Frage innerhalb app.component enthalten -

hier app.component.ts

@Component({ 
    selector: 'app-root', 
    templateUrl: './app.component.html', 
    styleUrls: ['./app.component.scss'] 
}) 

export class AppComponent { 
    currentUrl: string = null; 

    constructor(private router: Router, private currentRoute: ActivatedRoute) {} 

    ngOnInit() { 
    this.router.events.subscribe((val) => { 
     this.currentUrl = this.router.url; 
    }); 
    } 
} 

app.component.html (nur die Taste Kürze)

<div class="fab-container"> 
    <button class="btn btn-warning btn-fab" (click)="fabAction()"> 
    + 
    </button> 

Die allgemeine Idee ist, dass, wenn diese Schaltfläche geklickt, Es führt die fabAction() Methode für die untergeordnete Komponente aus;

@Component({ 
    selector: 'app-course-list', 
    templateUrl: './course-list.component.html', 
    styleUrls: ['./course-list.component.scss'] 
}) 
export class CourseListComponent implements OnInit { 

    courses: Course[]; 
    showFilter: boolean = false; 

    constructor(
    private courseService: CourseService 
) { } 

    ngOnInit(): void { 
    this.getCourses(); 
    } 

    getCourses(): void { 
    this.courseService.getCourses().then(courses => this.courses = courses); 
    } 

    // Should execute this method when button is clicked on app component 
    fabAction(): void { 
    console.log('responding to click on parent component'); 
    this.showFilter = !this.showFilter; 
    } 
} 

</div> 

Eine Sache, nichts wert ist, dass jede Komponente wird eine eigene Aktion ist auszuführen, wenn die Fab-Taste auf der App-Komponente angeklickt wird, einige Modalverben geöffnet, andere/auszublenden Dinge zeigen wird, werden einige umleiten es so Es wäre wirklich schön, dieses Verhalten für die Komponente selbst angeben zu können.

Das Lesen der offiziellen eckigen Dokumente zu diesem Thema hat mich mit mehr Fragen als Antworten zurückgelassen. Also habe ich alles auf eine saubere Liste zurückgenommen in der Hoffnung, dass jemand eine bessere Lösung vorschlagen kann.

bearbeiten - Full-Markup für app.component.html wie gewünscht

<header *ngIf="currentUrl != '/landing'"> 
    <div class="brand"> 
    <img src="/assets/circle-logo.png" /> 
    </div> 
    <nav> 
    <div class="page-title"> 
     <h2>{{ page?.title }}</h2> 
     <h4>{{ page?.strapline }}</h4> 
    </div> 
    <ul class="header-nav"> 
     <li [routerLink]="['/courses']">Courses</li> 
     <li>Dashboard</li> 
     <li>Community</li> 
     <li>Blog</li> 
     <li>About</li> 
    </ul> 
    <div class="fab-container"> 
     <button class="btn btn-warning btn-fab" (click)="fabAction()"> 
     + 
     </button> 
    </div> 
    </nav> 
</header> 
    <router-outlet></router-outlet> 
<app-footer></app-footer> 

Hier ist mein app-Routing-Modul, in dem ich meine Routen definieren und welche Komponente, für die Route angezeigt werden (wie in der Tour des Helden Winkel getan 4 Demo)

const routes: Routes = [ 
    { path: '', redirectTo: 'landing', pathMatch: 'full' }, 
    { path: 'landing', component: LandingComponent }, 
    { path: 'courses', component: CourseListComponent }, 
    { path: 'course/:id', component: CourseComponent } 
]; 

@NgModule({ 
    imports: [ RouterModule.forRoot(routes) ], 
    exports: [ RouterModule ] 
}) 

export class AppRoutingModule {} 
+0

Wo erstellen Sie die Komponente? Können Sie mehr Code posten, der zeigt, wie Sie die untergeordnete Komponente einschließen? –

+0

Die Komponente wird vom eckigen Router über eine Router-Outlet angezeigt. Ich füge das vollständige Markup für 'app.component.html' zum ursprünglichen Post hinzu. – DLMousey

Antwort

1

Erstellen Sie einen Dienst mit einem RxJS-Betreff, den Sie beim Drücken der FAB-Taste next aufrufen. Dann in jeder Komponente, die interessiert, können Sie subscribe auf das Thema.

import { Subject } from 'rxjs/Subject' 

@Injectable() 
export class FabService { 
    clickSubject = new Subject(); 
} 

app.component

@Component(...) 
export class AppComponent { 

    constructor(private fabService: FabService) {} 

    fabAction() { 
    this.fabService.clickSubject.next(); 
    } 
} 

child.component

@Component(...) 
export class ChildComponent implements OnInit, OnDestroy { 

    private clickSub: Subscription; 

    constructor(private fabService: FabService) {} 

    ngOnInit() { 
    this.clickSub = this.fabService.clickSubject.subscribe(() => { 
     // FAB was clicked 
    }); 
    } 

    ngOnDestroy() { 
    this.clickSub.unsubscribe(); 
    } 
} 

Die einzige Situation, die ich denken kann, wo dies funktioniert möglicherweise nicht, wenn Sie faul Last Feature Module, da diese wird getrennte Instanzen des FabService erhalten (oder wie immer Sie es nennen). Ich denke, es gibt einen Weg dahin, aber ich kann mir das nicht von Kopf bis Fuß vorstellen.

+0

Das ist genau das, was ich brauchte, vielen Dank! Kann endlich aufhören, meinen Kopf gegen die Wand zu schlagen und etwas Fortschritt zu machen :) – DLMousey

1

die Komponenteninstanz auf die aktuelle Route zugeordnet zuzugreifen, könnten Sie die OnActivate Haken Schnittstelle nutzen diese Instanz in einen gemeinsamen Dienst einzustellen, wenn die Strecke i s aktiviert:

@Component({ 
    selector: 'some-cmp', 
    template: ` 
    <div>routerOnActivate: {{log}}</div> 
    `}) 
    export class AppComponent implements OnActivate { 
    constructor(private service:RouteStateService) { 
    } 

    routerOnActivate(next: ComponentInstruction, prev: ComponentInstruction) { 
     this.service.setCurrentRouteComponent(this); 
    } 
} 

Dann würden Sie in der Lage sein, die Komponenteninstanz zuzugreifen und Zugriff auf die Funktion auf diese Weise:

var component = this.service.getCurrentRouteComponent(); 
component.somefunction() 

Havent den Code getestet, schauen Sie bitte in this für weitere Informationen. Hoffe das hilft.

+0

Was ist? der Import für RouteStateService? Es scheint nicht in Angular 4 oder 5 zu sein. –

Verwandte Themen