Reputation: 550
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;
}
Upvotes: 1
Views: 764
Reputation: 8001
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.
Upvotes: 1