1

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();
    });
  }
}

Chu van tinh
  • 77
  • 1
  • 12
  • 2
    TrendAddOneComponent has a dependency named "downloadURL" but it seems to be missing according to the error. Do you provide it ? – serrulien Jul 31 '21 at 20:24
  • thanks I resolved that. I declare now this variable "downloadURL" before "constructor". that is downloadURL: Observable = new Observable(); – Chu van tinh Aug 01 '21 at 08:54

0 Answers0