Home > OS >  Use an Angular service from inside an export function
Use an Angular service from inside an export function

Time:06-23

I am not sure if this is doable, but can a service be called on its methods from inside an export function that's residing in a non-Angular component (e.g., just a Typescript file)?

Example: supposed we have this container-managed service that's easily injectable inside Angular components.

import { Injectable } from '@angular/core';
import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs";
import { Contact } from "@comp-store/data-model";
    
const URL = 'http://localhost:3333/api/contacts';
    
@Injectable({
  providedIn: 'root'
})
export class ContactsService {
    
  constructor(private http: HttpClient) {}

  sayHello(): string {
    return "hello there!";
  }
    
  all(): Observable<Contact[]> {
    return this.http.get<Contact[]>(URL);
  }
}

Now, suppose I have a mere Typescript file called utils.ts with this content only:

export const callTheService = () => {
  console.log('==> about to call the service...');
  // here, I need to get a handle on the `ContactsService` and if doable, then:
  //   - easy: call the sayHello() method to say hello, then
  //   - no easy: call the all() method to receive the returned contacts
}

With the setup above, I need to be able to issue a callTheService() call and have it deliver, is this possible?

Note: I know I can pass the service as a parameter but this is not the objective. The objective is to have the method summon the service from its inside.

=================

UPDATE: The more I think about it, the more I think it isn't doable. For example, I would have to write code like this inside an Angular component if I need to perform manual DI, something like:

function  contactServiceProvider(http: HttpClient): ContactsService {
  return new ContactsService(http);
}

export const CONTACT_SERVICE = 
  new InjectionToken<ContactsService>('CONTACT_SERVICE');

@Component({
  selector: 'comp-store-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss'],
  providers: [
    {
      provide: CONTACT_SERVICE,
      useFactory: contactServiceProvider,
      deps: [HttpClient]
    }
  ]
})
export class HeaderComponent {

  constructor(@Inject(CONTACT_SERVICE) private service: ContactsService) {}

  // ...

So, having code like this inside plain Typescript files is simply not possible.

CodePudding user response:

Angular 14 has inject() - there's some good examples from netbasal - you need to initially invoke the functions that use inject from the constructor (or property initializer) of an Angular component/service

import { inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

export function getRouteParam(key: string) {
  return inject(ActivatedRoute).snapshot.params[key];
}
@Component({
  selector: 'app-todo-page',
  templateUrl: './todo-page.component.html',
})
export class TodoPageComponent {
  id = getRouteParam('id');

  ngOnInit() {
    console.log(this.id)
  }
}

CodePudding user response:

Prior to Angular 14, no.

I assume somewhere further up the call stack you'll be in Angular code so could inject the service there, and pass the service as a parameter to your util function:

export const callTheService = (contactsService: ContactsService) => {
  contactsService.sayHello();
  // etc
}
  • Related