Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
298 views
in Technique[技术] by (71.8m points)

javascript - Call API-data with NGXS and set it in form-element

I have an API with some data. I am getting successfully data from this API. The Angular async PIPE in the template works. But I want to set the data from API directly in my form and not template. At the moment I am using for testing purposes default values.
I watched out for an example in the Angular Docs and googled a lot, but could not find any examples. I am using Angular in strict-mode.

Here is the Code:

Component:

settingsForm!: FormGroup;

@Select(SettingsState.getSettings)
settings$!: Observable<Settings[]>;

fooSettings: Settings;

ngOnInit(): void {
    this.store.dispatch(new GetSettings('222'));

    this.settings$.subscribe(((settings: Settings[]) => {
      this.fooSettings = DEFAULT_SETTINGS; // have to set default values. without the default values it does not work

      this.fooSettings = settings.find((filteredSettings: Settings) => {
        return filteredSettings.id === '222'; // I only want to get the data with the id 222. This part does not work as expected
      });
    }));
}

initForm(): void {
    const validations = [
        Validators.required,
        Validators.maxLength(2)
    ];

    this.settingsForm = this.formBuilder.group({
      players: [DEFAULT_SETTINGS.playerNames.length, validations], // I want to replace the DEFAULT_SETTINGS with the settings from the api
      rounds: [DEFAULT_SETTINGS.numberOfRounds, validations],
    });
  }

settings.state.ts:

@Selector()
static getSettings(state: SettingsStateModel): Settings[] {
    return state.settings;
}

@Action(GetSettings)
getSettings({ getState, setState }: StateContext<SettingsStateModel>, { id }: GetSettings): Observable<Settings[]> {
    return this.settingsService.getSettings(id).pipe(
        tap(result => {
            const state = getState();
            setState({
                ...state,
                settings: result,
            });
        }));
}

settings.model.ts:

export interface Settings {
  id: string;
  playerNames: Player[];
  numberOfRounds: number;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You might want to try something along these lines - don't create the form until the settings are loaded.

settingsForm!: FormGroup;

@Select(SettingsState.getSettings)
settings$!: Observable<Settings[]>;

fooSettings: Settings;

ngOnInit(): void {
    
    // Kick off call to load the settings
    this.store.dispatch(new GetSettings('222'));

    const validations = [
        Validators.required,
        Validators.maxLength(2)
    ]; 

    // When the settings state is updated via the API call, then get that setting 
    // entry and load it into the form.
    this.settings$.pipe(
     map(settings => settings.find(x => x.id === '222')),
     filter(setting => !setting),
     tap((setting: Settings) => {
      // Build the form from the loaded settings
      this.settingsForm = this.formBuilder.group({
          players: [setting.playerNames.length, validations],
          rounds: [setting.numberOfRounds, validations],
         });
     }),
     take(1),
    ).subscribe();

}

The dispatch call for GetSettings would probably be better triggered prior to this component being created (so it's already in the state), usually do this via a route resolver.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...