Ошибка при реализации CanDeactivate Guard - PullRequest
0 голосов
/ 15 июня 2019

В настоящее время я пытаюсь внедрить CanDeactivate Guard в мое угловое приложение, в котором уже есть HTTP-перехватчик для проверки подлинности.Но добавление защиты CanDeactivate вызывает ошибку, как упомянуто ниже.

Я зарегистрировал класс, который реализует интерфейс CanDeactivate в массиве провайдеров AppModule.Я зарегистрировал класс, который реализует интерфейс CanDeactivate в свойстве canDeactivate маршрута.

класс, реализующий интерфейс CanDeactivate:

export interface CanComponentDeactivate {
  canComponentDeactivate(): boolean;
}

@Injectable({providedIn: 'root'})
export class AppRegisterDeactivateGuard implements CanDeactivate<AppRegisterComponent> {
  canDeactivate(
    component: AppRegisterComponent,
    currentRoute: ActivatedRouteSnapshot,
    currentState: RouterStateSnapshot
  ): Observable<boolean>|Promise<boolean>|boolean {
    return component.isDeactivated;
  }
}

Компонент, в котором применяется защита деактивации:

@Component({
  selector: 'app-app-register',
  templateUrl: './app-register.component.html',
  styleUrls: ['./app-register.component.css']
})
export class AppRegisterComponent implements OnInit, CanComponentDeactivate {
  isDeactivated = false;
  @ViewChild('registrationForm') registForm: NgForm;
.
.
canComponentDeactivate() {
    if (this.registForm.dirty) {
      this.isDeactivated = confirm('You have modified changes in the form. \nDo you still want to navigate away ? ');
    }
    return this.isDeactivated;
  }
}

Определение маршрута для этой конечной точки:

...
{ path: 'register', component: AppRegisterComponent, canDeactivate: ['AppRegisterDeactivateGuard'] },

Массив провайдеров в модуле:

 providers: [{
    provide: HTTP_INTERCEPTORS,
    useClass: AppAuthInterceptService,
    multi: true
  }, AppRegisterDeactivateGuard],
  bootstrap: [AppComponent]

ОШИБКА

  StaticInjectorError(Platform: core)[AppRegisterDeactivateGuard]: 
    NullInjectorError: No provider for AppRegisterDeactivateGuard!
Error: StaticInjectorError(AppModule)[AppRegisterDeactivateGuard]: 
  StaticInjectorError(Platform: core)[AppRegisterDeactivateGuard]: 
    NullInjectorError: No provider for AppRegisterDeactivateGuard!
    at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:8896)
    at resolveToken (core.js:9141)
    at tryResolveToken (core.js:9085)
    at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:8982)
    at resolveToken (core.js:9141)
    at tryResolveToken (core.js:9085)
    at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:8982)
    at resolveNgModuleDep (core.js:21218)
    at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (core.js:21907)
    at getToken (router.js:2865)
    at resolvePromise (zone.js:831)
    at resolvePromise (zone.js:788)
    at zone.js:892
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
    at Object.onInvokeTask (core.js:17290)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
    at drainMicroTaskQueue (zone.js:601)
    at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:502)
    at invokeTask (zone.js:1744)

Ответы [ 2 ]

0 голосов
/ 15 июня 2019

TLDR; Измените свой маршрут на это:

{ path: 'register', component: AppRegisterComponent, canDeactivate: [AppRegisterDeactivateGuard] }

Измените поставщиков на это:

[{
    provide: HTTP_INTERCEPTORS,
    useClass: AppAuthInterceptService,
    multi: true
  }]

Более длинный ответ:

AppRegisterDeactivateGuard, имеющий как {providedIn: 'root'}, так и объявление его в качестве поставщика в модуле, не требуется. См. Документацию провайдера Angular .

Проблема здесь в сочетании с маршрутом и провайдерами.

Прямо сейчас ваш маршрут ищет токен через имя строки, однако он доступен через имя класса.

Используя @Injectable({providedIn: 'root'}), вы используете имя класса в качестве токена, и оно будет доступно как AppRegisterDeactivateGuard.

Имея в своих провайдерах AppRegisterDeactivateGuard, как у вас также сделает его доступным как AppRegisterDeactivateGuard.

Я не рекомендую это, но если вы хотите или должны ссылаться на него через строковые имена, вы можете поместить его в провайдеры следующим образом:

{ provide: 'AppRegisterDeactivateGuard', useClass: AppRegisterDeactivateGuard }
0 голосов
/ 15 июня 2019

Вам нужно передать интерфейс в обобщениях:

export class AppRegisterDeactivateGuard implements CanDeactivate<CanComponentDeactivate > {

, а затем реализовать метод canDeactivate

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