Ngrx-forms validation not working #4557
Replies: 1 comment
-
ngrx-forms is not a part of the NgRx org. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Good afternoon,
I'm writing you because few days ago I started to go deep using ngrx-forms and everything works fine till I tried to manage the validation. I tried all the things but is not working and this is my use case.
I have this actors.reducer.ts file with this content:
import { Action, createFeature, createReducer, on } from "@ngrx/store";
import { ActorDto } from "../../types/actor/actor-dto";
import * as ActorActions from 'src/app/store/actor/actors.actions';
import { createFormGroupState, createFormStateReducerWithUpdate, FormGroupState, onNgrxForms, onNgrxFormsAction, SetValueAction, updateGroup, validate } from "ngrx-forms";
import { required, greaterThanOrEqualTo, minLength } from 'ngrx-forms/validation';
export interface ActorFormValue {
id?: string;
name: string;
dateOfBirth?: any;
picture?: string | File;
}
const updateFormState = updateGroup({
name: validate((value) => {
console.log('Validating Name:', value);
return required(value);
}),
});
export const formReducer = createFormStateReducerWithUpdate(updateFormState);
const initialActorFormState = createFormGroupState(
'actorForm',
{
id: null,
name: '',
dateOfBirth: ''
}
);
interface State {
actors: ActorDto[];
actorForm: FormGroupState;
actorImg: string;
loading: boolean;
errors: string[] | null;
}
export const initialState: State = {
actors: [],
actorForm: initialActorFormState,
actorImg: null,
loading: false,
errors: null
};
// With CreateFeature, the feature name and reducer are passed to it
export const actorsFeature = createFeature({
name: 'actors',
reducer: (state: State | undefined, action: Action) => {
// Call the main reducer first
const baseReducer = createReducer(
initialState,
onNgrxForms(), // Handle ngrx-forms actions automatically
onNgrxFormsAction(SetValueAction, (state, action) => {
console.log('Ngrx Forms Action:', action);
return state;
}),
// Actors list
on(ActorActions.loadActors, (state) => ({
...state,
loading: true,
errors: []
})),
on(ActorActions.loadActorsSucess, (state, { actors }) => ({
...state,
actors,
loading: false
})),
on(ActorActions.loadActorsFailure, (state, { errors }) => ({
...state,
errors,
loading: false
})),
// Other actions (add, update, delete actors)
// ...
)(state, action); // Apply the base reducer
});
then i have an actor-form.component.ts file with this content and this template:
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { ActorDto } from '@models/actor/actor-dto';
import { FormBuilder, FormGroup } from '@angular/forms';
import { DateAdapter } from '@angular/material/core';
import { filter, map, Observable, Subscription, take } from 'rxjs';
import { EventService } from 'src/app/event-service';
import { Router } from '@angular/router';
import { select, Store } from '@ngrx/store';
import { ActorFormValue, actorsFeature } from '@store/actor/actors.reducer';
import * as ActorActions from '@store/actor/actors.actions';
import * as ActorSelectors from '@store/actor/actors.selectors';
import { FormGroupState, NgrxValueConverters } from 'ngrx-forms';
import { base64ToFile, toConsole } from '@shared/utilities/common-utils';
import { MatDatepickerInputEvent } from '@angular/material/datepicker';
@component({
selector: 'app-actor-form',
templateUrl: './actor-form.component.html',
styleUrls: ['./actor-form.component.css']
})
export class ActorFormComponent implements OnInit, OnDestroy {
@input()
model: ActorDto;
@input()
action: string;
actorForm$: Observable<FormGroupState>;
dateValueConverter = NgrxValueConverters.dateToISOString;
loading$!: Observable;
vm$ = this.store.select(ActorSelectors.selectActorsListViewModel);
form: FormGroup;
archiveSelectedEvt: string = '';
imageChanged: boolean = false;
actorsSubscription: Subscription = new Subscription();
constructor(private formBuilder: FormBuilder, private dateAdapter: DateAdapter,
private eventService: EventService,
private router: Router, private store: Store) {
this.dateAdapter.setLocale('en-GB');
this.actorForm$ = this.store.select(ActorSelectors.selectActorForm);
}
ngOnInit(): void {
}
onDateChange(event: MatDatepickerInputEvent) {
const date = event.value;
const dateString = date.toISOString().split('T')[0];
this.store.dispatch(ActorActions.updateDateOfBirth({ date: dateString }));
}
onSave = () => {
this.actorForm$
.subscribe(formState => {
if(formState.isValid) {
console.log('Actor form is valid');
}
else {
console.log('Actor form is not valid');
// Mark all fields as touched to trigger validation messages
Object.keys(formState.controls).forEach(controlName => {
const control = formState.controls[controlName];
control.touched = true; // Set touched to true
});
}
});
/*
this.actorForm$
.subscribe(formState => {
if(formState.isValid) {
const actor = formState.value;
let updateActorPayload = { ...actor, id: actor?.id };
}
ngOnDestroy(): void {
this.actorsSubscription.unsubscribe();
this.store.dispatch(ActorActions.resetActorForm());
}
}
<ng-container *ngIf="actorForm$ | async as formState">
<form class="form" [ngrxFormState]="formState" (submit)="onSave()">
Name
<input [ngrxFormControlState]="formState.controls.name" matInput required placeholder="Ex.: Drama">
<div *ngIf="formState.controls.name.errors?.required">
Name is required.
My form is loaded fine, but when I'm in the name field and I leave it without entering any value, when i go to inspect the Redux tab in Chrome to see my state, there are not any validation errors regarding the name field.
Would you be kind to help me with this issue, please?
Thanks in advance and I will be waiting for your feedback.
Best regards,
Ernesto.
Beta Was this translation helpful? Give feedback.
All reactions