0

I have an InjectionToken like:

export const SOURCE_DATA_INJECTION_TOKEN =
    new InjectionToken<CustomObject[]>('All Source Data', {
      providedIn: 'root',
      factory: () => {
        // Returns all source
        return someArrayData // This data is read from a local .json file;
      }
    });

And my component uses it directly as it should,

@Component({})
export class SourceManager {
  sourceDataList: CustomObject[] = inject(SOURCE_DATA_INJECTION_TOKEN);
}

Now, I have to upgrade my INJECTION_TOKEN to return data based on the source selected by the user in Component. Updates in the component will look like this:

@Component({})
export class SourceManager {
  selectedSource: SourceEnum = SourceEnum.SomeSource1

  sourceDataList: CustomObject[] = inject(SOURCE_DATA_INJECTION_TOKEN);
}

This selectedSource can be changed from UI. I want to send this selectedSource enum to my injection token and instead of returning all sources, now the token will be returning filtered data.

I see factory method can have parameter as well, can I somehow pass selectedSource to it?

itsji10dra
  • 4,603
  • 3
  • 39
  • 59
  • but why don't you use a service instead of token injection? – Chris Apr 05 '23 at 07:35
  • @Chris I know `Service` can easily overcome this. And service will result in a lot of code refactoring, I hope this can be done by modifying the current implementation. – itsji10dra Apr 05 '23 at 08:36
  • Why not filtering the `sourceDataList` after injecting the complete list into it? – derstauner Apr 05 '23 at 08:45
  • @derstauner This is not exactly my use case. I just refined it for SO. Consider loading data from different JSON file based on `selectedSource`. Every source has a specific JSON file to load data. – itsji10dra Apr 05 '23 at 09:21

1 Answers1

0

Without changing SOURCE_DATA_INJECTION_TOKEN into observable you do not have too many options, unfortunately. Right now I can think only about this

https://stackblitz.com/edit/angular-easguk?file=src%2Fmain.ts


type Datum = {
  id: string;
};
export const SOURCE_ADD_TOKEN = new InjectionToken<Subject<Datum>>(
  'Add Source',
  {
    providedIn: 'root',
    factory: () => new Subject<Datum>(),
  }
);

export const SOURCE_DATA_INJECTION_TOKEN = new InjectionToken<Datum[]>(
  'All Source Data',
  {
    providedIn: 'root',
    factory: () => {
      let items = [{ id: '0' }];
      inject(SOURCE_ADD_TOKEN).subscribe((newItem) => {
        items.push(newItem);
      });
      return items;
    },
  }
);

@Component({
  selector: 'my-app',
  standalone: true,
  template: `
     We have {{data.length}} item(s)
     <button (click)="onChangeClick()">Add</button>
  `,
})
export class App {
  public data = inject(SOURCE_DATA_INJECTION_TOKEN);

  private add$ = inject(SOURCE_ADD_TOKEN);

  onChangeClick() {
    this.add$.next({ id: nanoid() });
  }
}
Lonli-Lokli
  • 3,357
  • 1
  • 24
  • 40