Введенный сервис не определен в функции, но не ngInit - PullRequest
0 голосов
/ 28 июня 2019

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

Component

export class TreeComponent implements OnInit {
  constructor(private store: Store<AppState>,
    private cdRef: ChangeDetectorRef,
    private injector: Injector,
    private locationService: LocationService) { }

async ngOnInit() {
  await this.store.pipe(
  select('auth'),
  map(async (authState) => {
    if (authState.isAuthenticated) {
      console.log(this.locationService);
      this.data.push(await this.injector.get(LocationService).getBaseLocation().toPromise());
      this.cdRef.detectChanges();
      console.log(this.locationService);
    }
  })
  ).toPromise();
}
/* Ommited where not used */

public hasChildren(node: any): boolean {
  console.log(node);
  console.log(this.locationService); <-- undefined
  console.log(this.injector); <-- undefined
  //Check if the parent node has children.
  return true;
}

CoreModule

@NgModule({
  declarations: [ShellComponent, SidebarComponent, TreeComponent],
  imports: [
    CommonModule,
    RouterModule,
    SharedModule,
    TreeViewModule,
    FormsModule
  ],
  exports: [

  ],
  providers: [AuthService, Shell, LocalizationService, LocationService]
})
export class CoreModule {
  constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
    if (parentModule) {
      throw new Error(`${parentModule} has already been loaded. Import Core module in the AppModule only.`);
    }
  }
}

App Module

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    HttpClientModule,
    BrowserModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: (createCustomTranslateLoader),
        deps: [HttpClient]
      },
      missingTranslationHandler: {
        provide: MissingTranslationHandler,
        useClass: CreateMissingTranslationHandler,
        deps: [HttpClient]
      },
      useDefaultLang: true
    }),
    StoreModule.forRoot(reducers, { metaReducers }),
    !environment.production ? StoreDevtoolsModule.instrument({
      maxAge: 25 //  Retains last 25 states
    }) : [],
    EffectsModule.forRoot([AuthEffects]),
    CoreModule,
    SharedModule,
    ProductionOverviewModule,
    AppRoutingModule,
    BrowserAnimationsModule
  ],
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: (initI18n),
      deps: [
        HttpClient,
        TranslateService,
      ],
      multi: true
    },
    { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

LocationService

const headers = new HttpHeaders({
 'Content-Type': 'application/json'
});

@Injectable()
export class LocationService {
public currentPlant: BehaviorSubject<Location>;

constructor(private http: HttpClient) {
 this.currentPlant = new BehaviorSubject<Location>(null);
}

getBaseLocation(): Observable<Location> {
 return this.http.get<Location>(environment.API_BASE_URI + '/Location/GetBaseLocation', { headers: headers })
  .pipe(map(location => {
    this.currentPlant.next(location);
    location.childeren = [];
    return location;
  }));
}

getChildLocations(locationId: string): Observable<Location[]> {
   return this.http.get<Location[]>(environment.API_BASE_URI + `/Location/GetLocationTree?upperLocationID=${locationId}`, { headers: headers })
  .pipe(map(location => {
    return location;
  }));;
}
}

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

Ответы [ 2 ]

1 голос
/ 28 июня 2019

Предположим, что функция hasChildren вызывается из компонента kendo-treeview в вашем HTML, вы должны использовать функцию Function.prototype.bind :

<kendo-treeview
  kendoTreeViewExpandable
  [nodes]="data"
  textField="text"
  [children]="fetchChildren"
  [hasChildren]="hasChildren.bind(this)">
                 ^^^^^^^^^^^^^^^^^^^^^^
</kendo-treeview>

Что происходит здесь, когда выполняется hasChildren, область действия отличается , и поэтому this не то, что вы ожидали.

Функция bind возвращает новую функцию, связанную с определенным вами this.

1 голос
/ 28 июня 2019

Это связано с тем, что функция hasChildren вызывается из компонента kendo-treeview, поэтому перед ее передачей необходимо связать текущий контекст с функцией.

Изменение

[hasChildren]="hasChildren"

К

[hasChildren]="hasChildren.bind(this)"

Подойдет

...