I got stuck 2 days before about this error during using Observable of rxjs in order to upload images and videos to firebase google cloud. But I don't understand what I injected wrong in my code. pls, help me. I'm using Angular 12, typescript 4.2.3. I found a same question here: NullInjectorError: R3InjectorError(AppModule)[Router -> Router -> Router]: NullInjectorError: No provider for Router
here is my app.module.ts file:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LoginComponent } from './modules/login/login.component';
import { HomeComponent } from './pages/home/home.component';
import { MenuComponent } from './shared/menu/menu.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatToolbarModule} from "@angular/material/toolbar";
import {MatButtonModule} from "@angular/material/button";
import {MatIconModule} from "@angular/material/icon";
import { ServicesComponent } from './pages/services/services.component';
import { AboutComponent } from './shared/about/about.component';
import { SliderComponent } from './shared/home_child/slider/slider.component';
import { PartnerComponent } from './shared/home_child/partner/partner.component';
import { IntroductionComponent } from './shared/home_child/introduction/introduction.component';
import { CustomerCommentsComponent } from './shared/home_child/customer-comments/customer-comments.component';
import { NewsComponent } from './shared/home_child/news/news.component';
import { NewlesterComponent } from './shared/home_child/newlester/newlester.component';
import { FooterComponent } from './shared/footer/footer.component';
import { MenudownComponent } from './shared/menudown/menudown.component';
import { FooterCopyrightComponent } from './shared/footer-copyright/footer-copyright.component';
import { MatGridListModule} from "@angular/material/grid-list";
import { MatSidenavModule} from "@angular/material/sidenav";
import { MatMenuModule} from "@angular/material/menu";
//bootstrap: https://valor-software.com/ngx-bootstrap/#/documentation
import { CarouselModule } from 'ngx-bootstrap/carousel';
import {A11yModule} from "@angular/cdk/a11y";
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
// state management
import { StoreModule, MetaReducer } from '@ngrx/store';
import { ScrolltopComponent } from './shared/generell-component/scrolltop/scrolltop.component';
// toast notification
import { ToastrModule } from 'ngx-toastr';
import {AuthService} from "./services/auth";
import {A} from "@angular/cdk/keycodes";
// NgRx
import { Authreducer} from "./store/reducers/auth.reducer";
import {EffectsModule} from "@ngrx/effects";
import {AuthEffects} from "./store/effects/auth.effects";
import { StoreDevtoolsModule} from "@ngrx/store-devtools";
import { metaReducers, reducers} from "./store/app.states";
import { TrendradarComponent } from './pages/trendradar/trendradar.component';
import { PortfolioComponent } from './pages/portfolio/portfolio.component';
import { RoadmapComponent } from './pages/roadmap/roadmap.component';
import { ListtrendsComponent } from './pages/listtrends/listtrends.component';
import {GraphQLModule} from "./graphql.module";
import { TrendDetailComponent } from './pages/trend-detail/trend-detail.component';
import { TrendAddOneComponent } from './pages/trend-add-one/trend-add-one.component';
// tool tip
import { TooltipModule} from "ngx-bootstrap/tooltip";
// fire storage
import { AngularFireModule } from '@angular/fire';
import { AngularFireDatabaseModule } from '@angular/fire/database';
import { AngularFireStorageModule } from '@angular/fire/storage';
import { environment } from '../environments/environment';
import { HttpClientModule } from '@angular/common/http';
import {HttpLinkModule} from 'apollo-angular-link-http';
@NgModule({
declarations: [
AppComponent,
LoginComponent,
HomeComponent,
MenuComponent,
ServicesComponent,
AboutComponent,
SliderComponent,
PartnerComponent,
IntroductionComponent,
CustomerCommentsComponent,
NewsComponent,
NewlesterComponent,
FooterComponent,
MenudownComponent,
FooterCopyrightComponent,
ScrolltopComponent,
TrendradarComponent,
PortfolioComponent,
RoadmapComponent,
ListtrendsComponent,
TrendDetailComponent,
TrendAddOneComponent
],
exports: [
MatSidenavModule
],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
MatToolbarModule,
MatButtonModule,
MatIconModule,
MatGridListModule,
MatSidenavModule,
MatMenuModule,
StoreModule.forRoot(reducers, {metaReducers}),
StoreDevtoolsModule.instrument({
maxAge: 25, // Retains last 25 states
//logOnly: environment.production, // Restrict extension to log-only mode
}),
EffectsModule.forRoot([AuthEffects]),
CarouselModule,
A11yModule,
FormsModule,
BrowserAnimationsModule,
ToastrModule.forRoot(),
ReactiveFormsModule,
GraphQLModule,
TooltipModule.forRoot(),
AngularFireModule.initializeApp(environment.firebaseConfig, 'cloud'),
AngularFireDatabaseModule,
AngularFireStorageModule,
HttpClientModule,
HttpLinkModule,
],
providers: [
AuthService,
],
bootstrap: [AppComponent]
})
export class AppModule {}
hier app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import {LoginComponent} from "./modules/login/login.component";
import {HomeComponent} from "./pages/home/home.component";
import {ServicesComponent} from "./pages/services/services.component";
import {AboutComponent} from "./shared/about/about.component";
import {ListtrendsComponent} from "./pages/listtrends/listtrends.component";
import {TrendradarComponent} from "./pages/trendradar/trendradar.component";
import {PortfolioComponent} from "./pages/portfolio/portfolio.component";
import {RoadmapComponent} from "./pages/roadmap/roadmap.component";
import {TrendDetailComponent} from "./pages/trend-detail/trend-detail.component";
import {TrendAddOneComponent} from "./pages/trend-add-one/trend-add-one.component";
const routes: Routes = [
{path: 'login', component: LoginComponent},
{path: '', component: HomeComponent},
{path: 'home', component: HomeComponent},
{path: 'services', component: ServicesComponent},
{path: 'projects', component: ServicesComponent},
{path: 'about', component: AboutComponent},
{ path: 'listtrends',
children: [
{ path: '', component: ListtrendsComponent },
{ path: ':id', component: TrendDetailComponent},
{ path: 'add/trend', component: TrendAddOneComponent},
]
},
{path: 'trendradar', component: TrendradarComponent},
{path: 'portfolio', component: PortfolioComponent},
{path: 'roadmap', component: RoadmapComponent},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
hier is view of listtrends:
<p class="text-center"><a routerLink="add/trend" class="btn btn-sm btn-success mb-2">Add new Trend</a></p>
the erros is showed in the component trend add one:
core.js:6456 ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(AppModule)[Observable -> Observable -> Observable]:
NullInjectorError: No provider for Observable!
NullInjectorError: R3InjectorError(AppModule)[Observable -> Observable -> Observable]:
NullInjectorError: No provider for Observable!
at NullInjector.get (core.js:11077)
at R3Injector.get (core.js:11243)
at R3Injector.get (core.js:11243)
at R3Injector.get (core.js:11243)
at NgModuleRef$1.get (core.js:25325)
at Object.get (core.js:25039)
at lookupTokenUsingModuleInjector (core.js:3342)
at getOrCreateInjectable (core.js:3454)
at Module.ɵɵdirectiveInject (core.js:14704)
at NodeInjectorFactory.TrendAddOneComponent_Factory [as factory] (trend-add-one.component.ts:21)
at resolvePromise (zone.js:1213)
at resolvePromise (zone.js:1167)
at zone.js:1279
at ZoneDelegate.invokeTask (zone.js:406)
at Object.onInvokeTask (core.js:28645)
at ZoneDelegate.invokeTask (zone.js:405)
at Zone.runTask (zone.js:178)
at drainMicroTaskQueue (zone.js:582)
at ZoneTask.invokeTask [as invoke] (zone.js:491)
at invokeTask (zone.js:1600)
component trendaddone.ts
import { Component, OnInit } from '@angular/core';
import {FormGroup, FormControl, FormArray, FormBuilder, Validators} from '@angular/forms';
// Get data by gql query
import {Apollo} from 'apollo-angular';
import gql from 'graphql-tag';
import {Router, ActivatedRoute} from '@angular/router';
import {NotificationService} from '../../services/notification.service';
import {AngularFireDatabase} from "@angular/fire/database";
import {AngularFireStorage} from "@angular/fire/storage";
import { HttpClientModule } from '@angular/common/http';
import {Observable,of, from } from 'rxjs';
import {finalize, map} from "rxjs/operators";
@Component({
selector: 'app-trend-add-one',
templateUrl: './trend-add-one.component.html',
styleUrls: ['./trend-add-one.component.sass'],
})
export class TrendAddOneComponent implements OnInit {
form: FormGroup = this.formBuilder.group({});
categories:any = [];
images:any[] = []; // for preview images
videos:any[] = []; // for preview videos
uploadFilesImages:any[] = []; // for save images
uploadFilesVideos:any[] = []; // for save videos
// link images and videos after uploading
linkImages:any[] = [];
linkVideos:any[] = [];
constructor(
private formBuilder: FormBuilder,
private apollo: Apollo,
private router: Router,
private route: ActivatedRoute,
private notification: NotificationService,
private fb: FormBuilder,
private db: AngularFireDatabase,
public downloadURL: Observable<string>,
private storage: AngularFireStorage,
) { }
ngOnInit(): void {
this.getCategories();
this.form = this.formBuilder.group({
title: ['', Validators.required],
description: ['', Validators.required],
trendVideos: this.fb.array([
this.fb.group({
trend_videos: new FormControl('', [Validators.required]),
})
]),
trendImages: this.fb.array([
this.fb.group({
trend_images: new FormControl('', [Validators.required]),
})
]),
status: ['', Validators.required],
catId1: ['', Validators.required],
catId2: ['', Validators.required],
});
}
async add(valueInput: any) {
// validate form
if (this.form.invalid) {
this.notification.showError('Bitte validieren Sie Form', 'open-innovation.de');
return;
}
if ( this.uploadFilesImages.length > 0){
for await (let item of this.uploadFilesImages){
this.linkImages.push( await this.uploadImages(item));
}
}
if ( this.uploadFilesVideos.length > 0){
for await (let item of this.uploadFilesVideos){
this.linkVideos.push( await this.uploadVideos(item));
}
}
enum STATUS {
e = 'ACTIVE',
g = 'DEACTIVE',
b = 'BEENDET'
}
const _status = STATUS;
// add data to database
}
/**
* Handle Change of Images
*/
onFileImagesChange(event:any) {
if (event.target.files && event.target.files[0]) {
//console.log(this.uploadFilesImages);
let filesAmount = event.target.files.length;
for (let i = 0; i < filesAmount; i++) {
let reader = new FileReader();
reader.onload = (event: any) => {
// console.log(event.target.result);
this.images.push(event.target.result);
};
// for upload image
this.uploadFilesImages.push(event.target.files[i]);
reader.readAsDataURL(event.target.files[i]);
}
}
}
/**
* Handle Change of Videos
*/
onFileVideoChange(event:any) {
if (event.target.files && event.target.files[0]) {
let filesAmount = event.target.files.length;
for (let i = 0; i < filesAmount; i++) {
let reader = new FileReader();
reader.onload = (event: any) => {
// console.log(event.target.result);
this.videos.push(event.target.result);
};
// for upload video to frise base
this.uploadFilesVideos.push(event.target.files[i]);
reader.readAsDataURL(event.target.files[i]);
}
}
}
/**
* get Infor of all categories
*/
getCategories() {
this.apollo
.watchQuery({
query: gql`
query getCategories{
getCategories{
id
title
description
createdAt
createdBy
{
id
name
}
}
}
`,
variables: {}
})
.valueChanges.subscribe(result => {
this.categories = Array.of(result.data);
});
}
/**
* ************************************************************************************ FORM ARRAY
*/
// Video ----------------------------------------------------------------------------------------------------------
/**
* Video, Add and Remove question type Video
*/
trend_videos() {
return this.form.get('trendVideos') as FormArray;
}
removeQuestionVideo(index: number) {
this.trend_videos().removeAt(index);
}
// Images ----------------------------------------------------------------------------------------------------------
/**
* Image, Add and Remove question type image
* image would save on the google cloud
*/
trend_images() {
return this.form.get('trendImages') as FormArray;
}
removeQuestionImage(index: number) {
this.trend_images().removeAt(index);
}
/**
* ***********************************************************************************************************
*/
/**
* Upload Image to Firebase Cloud in Folder ImagesSurvey
* @output string url
*/
uploadImages(fileItem: any):any {
return new Promise((resolve, reject) => {
let URL:any;
const date = Date.now();
const filePath = `Masterthesis/${date}`; // where storaged
const fileRef = this.storage.ref(filePath); // where is the endpoint
const task = this.storage.upload(`Masterthesis/${date}`, fileItem);
task.snapshotChanges()
.pipe(
finalize(() => {
this.downloadURL = fileRef.getDownloadURL();
this.downloadURL.subscribe(url => {
if (url) {
URL = url;
resolve(URL);
}
console.log('Link image in function uploadImages is :' + URL);
});
})
)
.subscribe();
});
}
/**
* Upload Video to Firebase Cloud in Folder VideosSurvey
* @output string url
*/
uploadVideos(fileItem: any): any {
return new Promise((resolve, reject) => {
let URL: any;
const date = Date.now();
const filePath = `Masterthesis/${date}`; // where storaged
const fileRef = this.storage.ref(filePath); // where is the endpoint
const task = this.storage.upload(`Masterthesis/${date}`, fileItem);
task.snapshotChanges()
.pipe(
finalize(() => {
this.downloadURL = fileRef.getDownloadURL();
this.downloadURL.subscribe(url => {
if (url) {
URL = url;
resolve(URL);
}
console.log('Link video in function uploadImages is :' + URL);
});
})
)
.subscribe();
});
}
}