Как добавить CanDeactivate функциональность в компоненте? - PullRequest
0 голосов
/ 27 августа 2018

Я пытаюсь добавить функциональность CanDeactivate в свой компонент. У меня есть Форма, в которой есть one input поле и кнопка. Я хочу, если пользователь введет что-то в поле ввода и перейдет к следующему screen без отправки, появится диалоговое окно. Если пользователь введет yes из диалогового окна, то он перейдет к следующему компоненту, в противном случае он останется на том же экране.

вот мой код https://stackblitz.com/edit/angular-ctwnid?file=src%2Fapp%2Fhello.component.ts

import {CanDeactivate} from '@angular/router';
import { HelloComponent } from './hello.component';

export default class DeactivateGuard implements CanDeactivate<HelloComponent> {

  canDeactivate(component: HelloComponent): boolean {

    if (!component.canDeactivate()) {
      if (confirm('You have unsaved changes! If you leave, your changes will be lost.')) {
        return true;
      } else {
        return false;
      }
    }
    return true;
  }

}

в настоящее время, когда я что-то набираю в поле input и нажимаю кнопку next, это выдает ошибку

ERROR
Error: Uncaught (in promise): TypeError: Cannot read property 'ngInjectableDef' of undefined
TypeError: Cannot read property 'ngInjectableDef' of undefined
at resolveNgModuleDep (https://angular-ctwnid.stackblitz.io/turbo_modules/@angular/core@6.0.0/bundles/core.umd.js:9309:31)
at NgModuleRef_.get (https://angular-ctwnid.stackblitz.io/turbo_modules/@angular/core@6.0.0/bundles/core.umd.js:10003:16)
at PreActivation.getToken (https://angular-ctwnid.stackblitz.io/turbo_modules/@angular/router@6.0.0/bundles/router.umd.js:3014:25)
at MergeMapSubscriber.eval [as project] (https://angular-ctwnid.stackblit

Ответы [ 2 ]

0 голосов
/ 27 августа 2018

вы не прошли деактивную защиту в провайдерах на app.module.ts, отредактировали ваш stackbiltz

     providers: [TestService,TestResolver,DeactivateGuard  
  ]
0 голосов
/ 27 августа 2018

Я думаю, что идеальной реализацией было бы создание интерфейса, который позволял бы многократно использовать Guard.

Вот как:

import { Injectable } from '@angular/core';
import { CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

export interface CanComponentDeactivate {
  confirm(): boolean;
}

@Injectable()
export class DeactivateGuard implements CanDeactivate < CanComponentDeactivate > {
  canDeactivate(
    component: CanComponentDeactivate,
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): boolean {
    if (!component.confirm()) {
      return confirm('You have unsaved changes! If you leave, your changes will be lost.');
    }
  }
}

Тогда в этом CanComponentDeactivate интерфейсе должен быть реализован компонент, на котором вы должны разместить эту защиту. Вот как будет принудительно реализован метод confirm, откуда возвращаемое логическое значение - это то, что вы хотели бы проверить в методе canDeactivate вашей охраны.

Что-то вроде этого:

import { Component, Input } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { CanComponentDeactivate } from './deactivate.guard';

@Component({
  selector: 'hello',
  template: `<h1>Hello {{name}}!</h1>
      <form novalidate [formGroup]="sfrm" class="calform">
      <input type="text" formControlName="name"/>
      <button type="submit">submit</button>
      </form>
      <a [routerLink]="['/next']">next</a>
  `,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent implements CanComponentDeactivate {
  @Input() name: string;
  sfrm: FormGroup

  constructor(private fb: FormBuilder) {
    this.sfrm = this.fb.group({
      name: ['']
    });
  }

  confirm() {
    return this.sfrm.submitted || !this.sfrm.dirty;
  }

}

И последнее - добавить Стража в качестве поставщика. В конце концов, это услуга. Так что добавьте его в массив providers:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule, Routes } from '@angular/router';

import { ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
import { ErrorComponent } from './error.component';
import { DeactivateGuard } from './deactivate.gaurd';

import { TestService } from './test.service';
import { TestResolver } from './test.resolver';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { NextComponent } from './next/next.component';
const routes: Routes = [{
    path: 'home',
    component: HelloComponent,
    canDeactivate: [DeactivateGuard]
  },
  {
    path: 'next',
    component: NextComponent
  },
  {
    path: '',
    redirectTo: '/home',
    pathMatch: 'full'
  }
];
@NgModule({
  imports: [
    BrowserModule,
    ReactiveFormsModule,
    RouterModule.forRoot(routes),
    HttpClientModule, 
    FormsModule
  ],
  declarations: [
    AppComponent,
    HelloComponent, 
    ErrorComponent, 
    NextComponent
  ],
  bootstrap: [AppComponent],
  providers: [
    TestService, 
    TestResolver, 
    DeactivateGuard
  ]
})
export class AppModule {}

Это должно заставить охранника работать на вас. Вот ваш Обновленный StackBlitz

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...