Как заставить Nativescript-ui-sidedrawer выполнять боковую навигацию?

Я пытаюсь реализовать боковую навигацию в своем приложении с помощью бокового ящика.

В моем приложении есть компонент «Пуск», который представляет собой своего рода страницу «Приветствие» и 32 «Темы» с необходимым контентом.

Мне нужно, чтобы пользователь мог переходить от темы к теме, используя содержимое Sidedrawer, не возвращаясь на стартовую страницу.

Теперь я могу успешно перейти со стартовой страницы, например, на «Тема 6». Но для того, чтобы перейти к другой теме, скажем «Тема 12», мне нужно нажать «назад» и вернуться на начальный экран. Кнопки темы в боковом ящике просто не работают, когда я нахожусь на экране темы.

Вот код:

app.component.html с боковым ящиком

<RadSideDrawer [drawerTransition]="sideDrawerTransition">
  <GridLayout tkDrawerContent  rows="auto, *">
    <StackLayout class="sidedrawer-header">
    <Image src="res://header" stretch="aspectFit" ></Image>
    </StackLayout>
    <ScrollView row="1" class="sidedrawer-content">
       <StackLayout >
        <Button
        *ngFor="let topic of topics"
        [text]="topic.title"
        [class.selected]="isComponentSelected('/unitsContent/' + topic.id)"
        (tap)="onNavItemTap('/unitsContent/' + topic.id)"
        class="btn">
        </Button>
       </StackLayout>
    </ScrollView>
   </GridLayout>
<page-router-outlet tkMainContent></page-router-outlet>
</RadSideDrawer>

app.component.ts

import { Component, OnInit, ViewChild } from "@angular/core";
import { NavigationEnd, Router } from "@angular/router";
import { RouterExtensions } from "nativescript-angular/router";
import { DrawerTransitionBase, RadSideDrawer, SlideInOnTopTransition} from "nativescript-ui-sidedrawer";
import { Topic } from "./data/topic";
import { TOPICS } from "./data/topics-collection";
import { TopicService } from "./data/topic.service";
import { filter } from "rxjs/operators";
import * as app from "tns-core-modules/application";

@Component({
    selector: "ns-app",
    moduleId: module.id,
    templateUrl: "./app.component.html"
})
export class AppComponent implements OnInit {

    private _activatedUrl: string;
    private _sideDrawerTransition: DrawerTransitionBase;

    topics: Topic[];

    getTopics(): void {
      this.topicService.getTopics()
          .subscribe(topics => this.topics = topics);
    }

    constructor(private router: Router, private routerExtensions: RouterExtensions, private topicService: TopicService) {
        // Use the component constructor to inject services.
    }

    ngOnInit(): void {
        this.getTopics();

        this._activatedUrl = "/start";
        this._sideDrawerTransition = new SlideInOnTopTransition();

        this.router.events
        .pipe(filter((event: any) => event instanceof NavigationEnd))
        .subscribe((event: NavigationEnd) => this._activatedUrl = event.urlAfterRedirects);
    }

    get sideDrawerTransition(): DrawerTransitionBase {
        return this._sideDrawerTransition;
    }

    isComponentSelected(url: string): boolean {
        return this._activatedUrl === url;
    }

    onNavItemTap(navItemRoute: string): void {
        this.routerExtensions.navigate([navItemRoute], {
            transition: {
                name: "fade"
            }, clearHistory: true
        });

        const sideDrawer = <RadSideDrawer>app.getRootView();
        sideDrawer.closeDrawer();
    }
}

app-routing.module.ts

import { NgModule } from "@angular/core";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { Routes } from "@angular/router";

const routes: Routes = [
    { path: "", redirectTo: "/start", pathMatch: "full" },
    { path: "start", loadChildren: "~/app/start/start.module#StartModule" },
    { path: "unitsContent/:id", loadChildren: "~/app/unitsContent/unitsContent.module#UnitsContentModule" },

];

@NgModule({
    imports: [NativeScriptRouterModule.forRoot(routes)],
    exports: [NativeScriptRouterModule]
})
export class AppRoutingModule { }

app.module.ts

import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core";
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { NativeScriptUISideDrawerModule } from "nativescript-ui-sidedrawer/angular";

import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";

@NgModule({
    bootstrap: [
        AppComponent
    ],
    imports: [
        NativeScriptModule,
        AppRoutingModule,
        NativeScriptUISideDrawerModule
    ],
    declarations: [
        AppComponent,

    ],
    providers: [],
    schemas: [
        NO_ERRORS_SCHEMA
    ]
})

export class AppModule { }

unitsContent.component.ts компонент "Тема"

import { Component, OnInit } from "@angular/core";
import { RadSideDrawer } from "nativescript-ui-sidedrawer";
import { ActivatedRoute } from '@angular/router';
import { TopicService} from '../data/topic.service';
import { Topic } from '../data/topic';


import * as app from "tns-core-modules/application";

@Component({
    selector: "UnitsContent",
    moduleId: module.id,
    templateUrl: "./unitsContent.component.html"
})
export class UnitsContentComponent implements OnInit {
    topic: Topic;

    constructor(
      public route: ActivatedRoute,
      public topicService: TopicService
    ) {
        // Use the component constructor to inject providers.
    }

    ngOnInit(): void {
        // Init your component properties here.
        this.getTopic();
    }

    getTopic(): void {
      const id = +this.route.snapshot.paramMap.get('id');
  this.topicService.getTopic(id)
    .subscribe(topic => this.topic = topic);
     }

    onDrawerButtonTap(): void {
        const sideDrawer = <RadSideDrawer>app.getRootView();
        sideDrawer.showDrawer();
    }
}

unitsContent.component.html

<ActionBar class="action-bar">
  <NavigationButton ios:visibility="collapsed" icon="res://baseline_menu_white_24" (tap)="onDrawerButtonTap()"></NavigationButton>
  <Label class="action-bar-title" [text]="topic.title" horizontalAlignment="left"></Label>
</ActionBar>
<StackLayout>
<GridLayout rows="*, *, *, *" columns="*, *">
  <Button text="Button 1" row="0" col="0" rowSpan="3" class="btn"></Button>
  <Button text="Button 2" row="0" col="1"  rowSpan="3" class="btn"></Button>
  <Button text="Button 3" row="3" col="0" colSpan="2" class="btn"></Button>
</GridLayout>
</StackLayout>

unitsContent.module.ts

import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core";
import { NativeScriptCommonModule } from "nativescript-angular/common";

import { UnitsContentRoutingModule } from "./unitsContent-routing.module";
import { UnitsContentComponent } from "./unitsContent.component";

@NgModule({
    imports: [
        NativeScriptCommonModule,
        UnitsContentRoutingModule
    ],
    declarations: [
        UnitsContentComponent
    ],
    schemas: [
        NO_ERRORS_SCHEMA
    ]
})
export class UnitsContentModule { }

unitsContent-routing.module.ts какое-то время там нет маршрутов, но я планирую перейти "глубже" позже.

import { NgModule } from "@angular/core";
import { Routes } from "@angular/router";
import { NativeScriptRouterModule } from "nativescript-angular/router";

import { UnitsContentComponent } from "./unitsContent.component";

const routes: Routes = [
    { path: "", component: UnitsContentComponent },
];

@NgModule({
    imports: [NativeScriptRouterModule.forChild(routes)],
    exports: [NativeScriptRouterModule]
})
export class UnitsContentRoutingModule { }

person Daniel Deulin    schedule 25.04.2019    source источник
comment
Поскольку вы используете розетку маршрутизатора страниц в ящике, она сохраняет историю маршрутизатора. Установка clearHistory на true при навигации очистит предыдущие страницы в истории маршрутизатора.   -  person Manoj    schedule 25.04.2019
comment
Спасибо за ваш ответ. Изменено на истинное. Все еще не работает. Отредактировал тело вопроса.   -  person Daniel Deulin    schedule 25.04.2019
comment
Можете ли вы поделиться минимальным образцом Playground, где проблема может быть воспроизведена?   -  person Manoj    schedule 25.04.2019
comment
Конечно. Попытаюсь. Я смогу сделать это за 6-7 часов.   -  person Daniel Deulin    schedule 25.04.2019
comment
Вот пример игровой площадки, воссоздающий проблему play.nativescript.org/?template =play-ng&id=Lf87p6&v=7   -  person Daniel Deulin    schedule 25.04.2019
comment
Я не вижу проблемы. После перехода к теме 2 нажатие кнопки «Назад» просто закрывает приложение, не возвращаясь на страницу приветствия, как вы упомянули.   -  person Manoj    schedule 25.04.2019
comment
В данном случае это моя вина, так как я неправильно описал проблему. Мне нужно иметь возможность переходить от Темы 2 к Теме 1 или Теме 3 через SideDrawer. извините за это недоразумение   -  person Daniel Deulin    schedule 25.04.2019


Ответы (1)


Похоже, я нашел ответ сам. Оказалось, что это чистая вещь Angular. В своем приложении я имею в виду один и тот же компонент. Единственное, что меняется, это мой параметр маршрута. Маршрутизатор уничтожает и воссоздает компонент только тогда, когда он переходит на другой маршрут. Когда обновляются только параметры маршрута или параметры запроса, но маршрут остается прежним, компонент не будет уничтожен и воссоздан.

Я нашел ответ здесь: Router Navigate не вызывает ngOnInit когда та же страница

Поэтому я изменил свой unitsContent.component.ts следующим образом:

import { Component, OnInit } from "@angular/core";
import { RadSideDrawer } from "nativescript-ui-sidedrawer";
import { ActivatedRoute } from '@angular/router';
import { TopicService} from '../data/topic.service';
import { Topic } from '../data/topic';


import * as app from "tns-core-modules/application";

@Component({
    selector: "UnitsContent",
    moduleId: module.id,
    templateUrl: "./unitsContent.component.html"
})
export class UnitsContentComponent implements OnInit {
    topic: Topic;

    constructor(
      public route: ActivatedRoute,
      public topicService: TopicService
    ) {
        // This part forces the component recreation with the new params
       route.params.subscribe(val => {
         this.ngOnInit();
        });
    }

    ngOnInit(): void {
        // Init your component properties here.
        this.getTopic();
    }

    getTopic(): void {
      const id = +this.route.snapshot.paramMap.get('id');
  this.topicService.getTopic(id)
    .subscribe(topic => this.topic = topic);
     }

Так что это решило мою проблему.

person Daniel Deulin    schedule 25.04.2019