简体   繁体   中英

Angular: Issue with Singleton Service implemented via Dependency Injection

I have implemented Singleton Service(ie ApiService) and i'm using this singleton service in the ProductCatalog Module wherein we have two methods in the singleton Service, getData() and addData() , which list out data and adds the data to a private data array in ApiService service.

we have two components product-listing and product-update. we use this component to list the data from the private Data variable from ApiService.

Expectation is when we use addData() method of singleton service it should add new data to Data array and on navigating to /update should list the data from Data variable on product update component with newly add data.

Currently this is not happening whenever we add newData to data array via a addData() Method of Single service. we are getting only the initial state of the data array without reflecting the newly added data.

Therefore, looks like i'm missing some step or implementation. please help in resolving this issue.

Here is the reference to the code. https://stackblitz.com/edit/angular-2uyx3a

Ok I think you are navigating by changing the url in the browser as there is no way provided to navigate in the example provided, which surely would not work as when you change the url you are actually reloading your app, which deletes all data in your app memory.

Your service is working fine, you just need to navigate using the @angular/router, and no it can't handle manual url changes and no nothing else can do that.

But it will handle links through routerLink more on that here - router official docs

inside product-listing.component.html


product-listing works!

<p *ngFor="let item of sampleData">{{ item.id }} -{{ item.name }}</p>

<!-- Example of using routerLink -->
<a routerLink="/update">go to update</a>

it can also handle dynamic routing through Router service using navigateTo or navigateByUrl functions like this:

inside product-update.component.ts


 // product-update.component.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router'
import { FormGroup, FormControl, FormArray } from '@angular/forms';
import { ApiService } from '../../core/api.service';
@Component({
  selector: 'app-product-update',
  templateUrl: './product-update.component.html',
  styleUrls: ['./product-update.component.css']
})
export class ProductUpdateComponent implements OnInit {
  dataForm: FormGroup;
  
  // do not forget to import the service
  constructor(private api: ApiService, private router: Router) {}

  ngOnInit() {
    this.dataForm = new FormGroup({
      id: new FormControl(' '),
      name: new FormControl(' ')
    });
  }

  saveData() {
    this.api.addData({
      id: this.dataForm.controls.id.value,
      name: this.dataForm.controls.name.value
    });
    // Use of router service `navigateByUrl` to dynamically redirect to another view
    this.router.navigateByUrl('/listing')
  }
}

But for any of these routing methods to work you need to add RouterModule.forChild() to the imports of the module including these components declarations. Like this:

inside product-catalog.module.ts


import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms';
import {CoreModule } from '../core/core.module';
import { RouterModule } from '@angular/router';

import { ProductListingComponent } from './product-listing/product-listing.component';
import { ProductUpdateComponent } from './product-update/product-update.component';

@NgModule({
  imports: [
    CommonModule,    ReactiveFormsModule,
    CoreModule.forRoot(),
    RouterModule.forChild([]) // Add this to the imports
  ],
  declarations: [ProductListingComponent, ProductUpdateComponent]
})
export class ProductCatalogModule { }

If you use this and test your service as it is, you will find that it is working perfectly fine.

But again when you change the url in the browser manually you are reloading your app, which deletes all of the app memory/data unless saved at backend.

Here is the link to the edit project https://stackblitz.com/edit/angular-z2m9ri

Hope this was helpful

You don't need forRoot in core module. You already provided the service in root:

@Injectable(
  providedIn: 'root'
)

This means the service is available in the root injector of the app. The core module is useless in this context.

Here is your stackblitz code working

I recommend you take a look at Angular's documentations for more information:

Hierarchical Dependency injection

Singleton Services

One thing to note: if you refresh the browser or change the route from browser address bar the state will get lost.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM