Platform: Adding ngrx-forms implementation into platform

Created on 26 Sep 2017  ·  43Comments  ·  Source: ngrx/platform

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[x] Feature request
[ ] Documentation issue or request

What is the current behavior?


There is no ngrx-forms

Expected behavior:


Either bring in https://github.com/MrWolfZ/ngrx-forms into the platform, our build something that accomplishes the same goal.

Minimal reproduction of the problem with instructions:

Version of affected browser(s),operating system(s), npm, node and ngrx:

Other information:

Previous discussion: https://github.com/ngrx/core/issues/12

question

Most helpful comment

Here's what I messaged to Brandon couple of weeks ago.

image

All 43 comments

Here's what I messaged to Brandon couple of weeks ago.

image

@brandonroberts @MikeRyanDev @robwormald @vsavkin

_Any_ update would be really lovely. The last thing you could call an official, public, update on this was in January.

Even "we are currently not planing on doing this because _n_" or "we do not plan on doing this ourselves in foreseeable future and we do not trust people outside ngrx team enough to support any official library, so the best option is you try do it third party" would be really really great.

Don't take the angular approach of never addressing things.. please.

@fxck I’m not sure the value add here over angular’s forms reactive forms implementation. In fact, I’m not even sure that ngrx should have anything to do with forms - which are almost always best treated as local component state.

It’s not clear what you’re proposing, why, or what the benefits and drawbacks are. What problems are you solving?

Present a coherent proposal, and we’ll discuss it. “Take over this other repo from a third party” does not constitute such a proposal.

@robwormald this issue https://github.com/ngrx/core/issues/12 is full of reasons, whys and whats, and given its got almost 60 likes, I'd say I'm not the only one interested in ngrx forms (and honestly, almost 8k stars on redux forms speaks for itself as well)

which are almost always best treated as local component state.

I beg to differ, from my experience, if I had form state in store, my life would be million times easier, for example, being able to reset form state upon success action / effect is one of many use cases

Present a coherent proposal, and we’ll discuss it. “Take over this other repo from a third party” does not constitute such a proposal.

This I completely agree with, https://github.com/MrWolfZ/ngrx-forms is only a bridge between angular forms and ngrx and not the best one at that, what I suggest (read my message to Brandon) is completely standalone module.. and in fact, @MikeRyanDev was already working on a design doc, here are couple of snippets from it:

Async Validators

@Injectable()
class OnBlurNameUniqueValidator {
  constructor(
    private formValidator: FormValidator,
    private nameService: NameService
  ) { }

  @Effect() validate$ = this.formValidator
    .createAsyncValidator('isNameUnique')
    .mergeMap(({ formControl, createValidationAction }) =>
      formControl.blur$
        .withLatestFrom(formControl.value$, (_, name) => name)
        .switchMap(name =>
          this.nameService.isUnique(name)
            .map(isUnique => createValidationAction({
              valid: isUnique
            }))
            .catch(() => Observable.of(
              createValidationAction({ valid: false })
            ))
        )
    );
}

custom controls

interface FormControl<T> {
  disabled$: Observable<boolean>;
  value$: Observable<T>;

  acceptValueChanges(value$: Observable<T>): void;
  acceptTouchedChanges(value$: Observable<void>): void;
}

@Directive({
  selector: 'input',
  host: {
    '(input)': 'valueChanges.next($event.target.value)',
    '(blur)': 'touchedChanges.next()',
    '[disabled]': 'disabled',
    '[value]': 'value'
  }
})
export class InputFormControl {
  valueChanges = new Subject<string>();
  touchedChanges = new Subject<void>();
  disabled: boolean = false;
  value: string = '';

  constructor(control: FormControl<string>) {
    control.disabled$.subscribe(disabled => this.disabled = disabled);
    control.value$.subscribe(value => this.value = value);
    control.acceptValueChanges(this.valueChanges);
    control.acceptTouchedChanges(this.touchedChanges);
  }
}

creating forms

import { group, control } from '@ngrx/forms';

@Component({
  template: `
    <form ngrxForm="nameAndAge">
      <label>
        Name
        <input type="text" ngrxFormControl="name">
      </label>

      <label>
        Age
        <input type="number" ngrxFormControl="age">
      </label>
    </form>
  `
})
export class SomeFormComponent {
  form = group({
    name: control({
      disabled: false,
      asyncValidators: [ 'isNameUnique' ]
    }),
    age: control({
      disabled: false,
      validators: [ isOldEnough ],
    })
  });
}

function isOldEnough(age: number) {
  return {
    isOldEnough: {
      valid: age > 21
    }
  };
}

@robwormald Wasn't really thinking that ngrx would pull in some random 3rd party library, more so to see if there were thoughts into building one and incorporating it into the platform as the conversation hasn't progressed in almost a year.

I'm sure how most people use forms it wouldn't be beneficial to incorporate it into the store, but when the forms get large and complicated, redux really seems to help. My app can have 50+ fields that can change at any point depending on seed data (so dynamic forms), with some complex validations that modify the form in many ways (fields hiding and showing, required if x field has value y). I've gotten around the limitations, but I feel that a central store for all the form data would make it all more robust and easier to work with.

I know a huge amount of work has gone into angular/forms, and it would be a massive undertaking to try and replicate a similar feature set. I've looked into extending the existing forms library to try and incorporate into ngrx, but the time to do it hasn't really been available. I'm mostly curious to see what the community thinks as a solution, and if that means a new module in the platform, a 3rd party library, or merely docs on how to go about it with the current setup then I'm all helping out (as I'm sure many others are as well).

So is this back in discussion?

Another place where ngrx/forms would be useful are guards, when you want to use canDeactivate depending on some form state.

One of the core principles of Redux is single source of truth, and without such a connector, the source of truth becomes duplicated in an Angular specific class instance that lives inside a component and now encapsulates state information that the central store can't see without specific implementation work from the developers.

What if I want an indicator in my navbar of how many forms are currently invalid ?

Theory indicates that I would have to use a selector and look through multiple slices. But also redux theory indicates that there should be a single source of truth.

So if the actual answer is : update a slice manually depending on a source of truth that's outside of the centralized store, are we still following the 3 principles from Redux or is the ngrx implementation not supposed to follow these ?

I also think that if we use ngrx store & effects to load the form data from the server, which makes sense, again, we're dealing with two sources of truth without such a connector, where the data we received from the server is in the store, but the latest version lives inside the angular reactive form.

but the latest version lives inside the angular reactive form.

Yeah, that's a classic.

  currentText$ = this.post$
    .filter((post) => !!post)
    .take(1)
    .switchMap(
      (post) => this.contentForm.instance
        .get('text')
        .valueChanges
        .startWith(post.text)
    );

Another problem is, that you don't always have access to the form instance, I usually try to put the form instance into the "smart" component and pass it down to the dumb components, but there are cases where you want to show current data in a component but the form instance is in different component tree branch altogether and if this happens to be a component that is a route, you can't even put the form instance to the common component tree parent node and pass it down with inputs. So you end up saving the form instance into a service.. and basically replicating store. It sucks.

Also optimistic updates. You send request, add data to store, reset form.. it fails, what now? Again, you need to save form state before the request happens somewhere, inject effects to get to the fail stream (to restore data), or success stream (to reset form). Words can't describe how a proper forms integration would help me in daily work.

Words can't describe how a proper forms integration would help me in daily work.

I couldn't agree more. More concise, granular control over complex forms via a proper integration would be a godsend.

@robwormald Sorry for pinging you back here as I know you are busy (working on Angular Elements which I’m super excited for). I just wanted to try and get some more info here as we are around a year since the original issue was filled.

So what I didn’t want this issue to come across as is “I would like this big, large new feature, go out and build it” as I know this is a open source project not backed by anyone that is very stable.

@fxck I feel has been pretty vocal about the reasons why we think this new addition would make sense. If you disagree with what’s posted I would love to here your counterpoints to it and maybe we can get work on some docs on how to approach some of these situations. Or I can work on a sample project that highlights some of the issues the community and myself have found, and perhaps it’s a lack of knowledge that that could be worked around.

I am more then happy to get my hands dirty and work on something that could work, but I don’t feel experienced enough to architect out this solution without guidance from some of the top contributors on here (and have it ultimately help no one but myself and not be adopted).

If perhaps @brandonroberts , @MikeRyanDev could also weigh in on why or why not this should be built, then we could hopefully move forward on something. Whether that is building something into the platform, are even just mentioning forms in the docs in some way, I think it would help those who come to ngrx looking for how they handle their forms.

There was some activity on Mike's old design doc (the one I pasted those snippets from here) over the holidays. So hopefully we'll get some official reply on what's going on, what the plans are, eventually.

To anyone interested on the "official" update, you might want to read this gitter discussion.

Anyway, I've been thinking about how to deal with some of the problems mentioned both here and in https://github.com/ngrx/core/issues/12, mainly these two use cases:

1) how to initially fill in the data
2) how to reset form state (either fully, including values, or setting it to pristine and resetting submitted state.) on any success (add, update)

I decided to go with a service, rather than saving a big mutating class (FormGroup) to actual store, which seemed like a bad idea.

The idea was to:

  • create all the form instances (FormGroup/FormControl) inside the topmost module / route they belong to
  • "register" them inside my service, that was provided on the module, under a unique id
  • inject the service in a smart component, get form instance, pass it down to a dumb form component that has the actual form elements
  • emit an event after this dumb component was AfterViewInited, passing up reference to NgForm and updating the service with reference to it
  • inject the service into the effect and use it

    • inside a tap of load success to patchValue

    • inside update success to reset value

    • inside update request to get the current values

There are couple of problems.

1) it's a lot of code, especially getting the NgForm reference to the service
2) it's impossible (or at least I haven't figure out) to get the current observable value, since you can't use withLatestFrom(this.formService.get('key').instance.valueChanges) because get would be called immediately, at time the instance wouldn't yet be registered and you can't use switchMap(() => this.formService.get('key').instance.valueChanges) either, because it would be empty until the next change, so you have to resort to using sync value map(() => this.formService.get('key').instance.value)

I ultimately decided it's way too much code, way too much boilerplate, way too hacky solution. Angular (not so) reactive forms simply do not fit well into ngrx ecosystem.

The way I see it, given that there won't really be an official @ngrx/forms package we, as a community, or the part interested in forms, have two options.

Embrace https://github.com/MrWolfZ/ngrx-forms give it enough feedback to make it a thing (which I'm not a fan of, it being only a bridge between angular forms will bite us in the arse eventually), or try and create coordinated effort to create our own @ngrx/forms, perhaps taking as much ideas from popular matured redux forms libraries as possible..

@fxck Maybe one of us should startup a repo for a lib, i would contribute, as i'm desperate for a better solution to my plethora of forms in my applications, both professionally (my staff included) and personally. I too am not a fan of ngrx-forms.

@fxck @Kaffiend could you elaborate on why you are not fans of ngrx-forms? I know I have made some opinionated design decisions and I would be really interested in whether it would be possible to change the library to fit your requirements.

In terms of it being just a bridge between @angular/forms and ngrx I cannot follow that argument. The only interaction/dependency is the re-use of the ControlValueAccessor concept to allow easier integration with third party components that were designed for @angular/forms (which there are many of that I am sure wouldn't want to make ngrx-specific changes). The rest of the library is written completely from scratch. This @angular/forms integration could even be refactored into a separate npm module to get rid of the dependency completely (the code already supports this easily).

@MrWolfZ this is the main thing that turned me off from ngrx-forms There may be other ways to utilize the library, and perhaps you can enlighten me :) but i have no interest in implementing forms in that manner. Beyond that i have not looked further into the library. I would just as well add another reducer than template it in a string. Telerik took a similar approach to templates in Kendo UI and it was always more pain than gain, until they decided to rebuild native.

@Kaffiend I am not sure I get what you mean. The code you linked is from the example application and is only for outputting the example code in the UI of the example application itself (if you browse to the example application here you can see that there are tabs at the top that show the code). What you linked is in no way being executed or required to use ngrx-forms. I simply copy & pasted the code into the component. Maybe I should clarify this with a comment in the code.

If you look at the other files besides the component here you can see that the code in the code files is (almost) the same as the one inside the component.

But maybe I am simply misunderstanding your post?

Also, if it would be desired to create actual form element components (like redux forms does, not sure if you mean that by "native") I think that would be easy enough to achieve as a layer on top of ngrx-forms.

I think i'm misunderstanding the example and the implementation. Apologies, i need to take another look after some coffee 😄

So, @MrWolfZ it appears I greatly underestimated the library and I make no excuse as to why, plain and simple i skimmed the library and formed an assumption and it was wrong. After finding the documentation and getting started, that i clearly missed the first time, all was apparent. Seeing code in comments or strings haunts me from the horror show of Kendo UI templates in its early days for form integrations.

Sorry for making you relive the nightmares from your past ;)

If you have any suggestions on how I can improve the library I'd be happy to hear them (and accept contributions of course). ngrx-forms is my first open source project and its interesting to see how the ecosystem works and how libraries evolve.

@MrWolfZ it's been a while since I looked into it, but what I'm sure that two things I disliked the most were the idea of having to manually put each form into the state and do your own reducing. This should be the responsibility of the form. The other thing was using standard select to get the form state and then using that to "set control state".

The way I imagine this should work is:

  • you put FormsConnectingModule into you app module, which internally creates a feature state called forms (or it can be optional, just as StoreRouterConnectingModule.forRoot({ stateKey: 'router' }) is)
  • in your component, you wouldn't have to use store to get the controls, you'd just use a path, either
<form ngrxFormState="uniqueKey">
  <input type="text" ngrxFormControlState="someTextInput">
</form>

similar to what you can do with formControlName, alternatively, you'd provide the full path uniqueKey.someTextInput and it would internally select stateKey.uniqueKey.someTextInput, these would fire register form / field action, creating the forms state shape..

Some other things I'd consider:

1) tracking more state than what angular forms do, such as focus and blur
2) providing selectors / a wrapper service around Store...

constructor(private _forms: NgrxForms) {
  value$ = this._forms.pipe(
    byKey<FormKeyState>('uniqueKey'), 
    value() // errors(), focused(), valid().. 
  );
}

@fxck I see your points. I think this might be fairly easy to add to ngrx-forms. A couple of points/questions:

  • How would you handle validation etc.? Custom directives on the form elements that react to value changes? Services/Effects to validate forms by name with subscriptions to the store?
  • One advantage of the current approach of having to manually pass the control states to the elements is that the compiler can verify you are passing the states correctly and are accessing only controls that exist in the state. With your approach typos etc. would be much harder to spot. It's a trade-off between less boilerplate and compile-time safety. I went for the latter.
  • ngrx-forms already supports tracking some additional state (focus and blur can be opted in on a per-control basis) and even a mechanism to allow tracking your own custom state (see this part of the user guide)

Of course all of the design decisions I made are heavily influenced by how I personally use ngrx. For example I don't use selectors at all, so it is difficult for me to imagine how users would want an API to look like. That's where I depend on community input/contributions.

Look at @MikeRyanDev snippets I posted here https://github.com/ngrx/platform/issues/431#issuecomment-336033756 I think that should answer first two points ("these would fire register form / field action, creating the forms state shape.." was added in an edit, I'm all for creating the controls beforehand, while still keeping the path approach and thus being able to validate it).

What do you think, @MrWolfZ ?

I imagine it could work like this.

  • you add NgrxFormStoreConnectingModule.forRoot({ stateKey: 'forms' }) to your app module, which creates a feature state forms with StoreModule.forFeature(stateKey, ngrxFormsReducer) and provides NgrxFormStore
  • you inject NgrxFormStore<FormsState> into the module of the module you you have your form in, you call NgrxFormStore.register('uniqueFormKey', NgrxFormsGroup), where NgrxFormsGroup would be something along the lines of Mike's snippet, this NgrxFormsGroup, this register would dispatch [ngrx-forms] Register Control with the structure defined with the NgrxFormsGroup helper
  • your directives then accepts dot path to the form state, which you can validate whether they exist
  • if you need access to form store state, you'd call NgrxFormStore.state$.pipe(select('dot.path')), the reason you'd use NgrxFormStore.state$ instead of Store is because NgrxFormStore has internal knowledge of stateKey defined in root

@MrWolfZ

@fxck sorry, I didn't have any time during the last couple of days due to work stress. I'll answer you properly as soon as possible, but potentially it'll have to wait until the weekend :(

@fxck So, I finally found some time to write up my thoughts.

First of all, thank you for taking the time to come up with these ideas. However, I am missing a crucial part in your argument. You have a lot of ideas of how the API could look like. However, what I am even more interested in is _why_ the API should look like that. What are the benefits, what are the drawbacks? Below I will give you the pros and cons I see in your suggestions. And of course I will also give you my "_why_" for the API design I chose for ngrx-forms.

Pros:

  • less boilerplate
  • easier to debug due to all interaction with the form state happening through explicit actions (thereby being captured by tools like the redux devtools)
  • defining the form structure and sync validation functions in the component might be more intuitive for users
  • creating async validators as re-usable effects is a very cool idea that can save quite a bit of boilerplate

Cons:

  • no compile-time validation of form structure/control access
  • having most logic in components or services seems anti-redux
  • by only having the form state structure be defined implicitly through directives in the template or a form instance in the component instead of through an explicit state interface you always have to access controls by their name as a string instead of having the type system (and thereby IDE autocomplete) tell you/validate what controls exist on a given form (e.g. having to use NgrxFormStore.state$.pipe(select('form.someControl')) instead of just store.select(s => s.path.to.form.controls.someControl))
  • the form control directives that only take the name and find their parent group/array to register themselves have some issues with partial forms as discussed in this issue
  • dependency on rxjs (not per se bad since Angular apps will reference rx anyways but the less own dependencies the library has the better)

Now to my "_why_" for the design I chose:

I love functional programming. I also love reactive programming (and therefore all rx libraries). I have used both in many projects. However, in comparison of the two functional programming will always win for me. Therefore I decided that a) I want the full API to be properly and statically typed and b) have almost all the logic in pure functions and reducers. Also, by designing the API to be best accessible through reducers users are encouraged to put their own heavy-lifting logic in reducers as well (something I have often seen done wrong). The library and any user code also become a breeze to test due to all logic being inside reducers. I would pay for these benefits with some boilerplate any day.

As I mentioned before, I am always willing to extend the API to fit more use cases. However, since I would not be using the API in the ways you suggest (since the current design works just fine for everything I use it for) it would be difficult for me to properly iterate upon it. I strongly believe that the best APIs are designed by people that use them themselves (or as the saying goes "eat your own dogfood"). Therefore it would be great if you (or someone else who likes the API you suggest) could contribute to the library.

PS: I am of course biased towards my own design, but I try to control that bias as best I can. Yet at the same time I have built very large form-based applications with forms spanning hundreds of controls with the current version of the library and found the design to be very successful in handling such scenarios.

I like the current design, because it is more easy to read template code in my opinion.

<form *ngIf="formState$ | async as formState" [ngrxFormState]="formState">
  <div *ngFor="let itemState of formState.controls.items.controls; trackBy: trackByIndex;">
    <input [ngrxFormControlState]="itemState" type="text">
  </div>
  <div *ngIf="formState.controls.items.isInvalid">
    <span *ngIf="formState.controls.items.errors.maxLength">Too many items</span>
  </div>
</form>

Looking to the code, it is very clear that itemState is control of form.items. And more easy to pass partial state into child component. If you write a template like Angular's FormControlName, there will be less boilerplate. But you have to track down all code to figure out the parent and ancestors of the form control.

And thanks for great library @MrWolfZ, I hope ngrx-forms to be merged into official ngrx platform.

look how "easy" is to find out whether form control is required or not with reactive forms..

https://github.com/angular/material2/issues/2574
https://github.com/angular/angular/issues/13461

There's this https://www.youtube.com/watch?v=kPkTXdToYV0

It only shows how unnecessarily hard it is to work with forms. :/

3 principles from Redux. I personally think this should be the only argument necessary.

@fxck @MrWolfZ As a programmer I would quite welcome if ngrx-forms would merge with ngrx community - If there is a chance. I think it would give more courage to developers to use the library because then there is bigger hope that the library would outlived its creator.

I created a filter which should occurs when user input values in some input fields.

For instance, the user can entre a week number in an input field and then an action should be dispatched to execute the filter.

This is my input:

<input type="number" [min]="firstWeekInYear" [max]="weeksInYear" formControlName="week"></input>

This is the code which dispatches the action:

    this.filterForm.controls['weekForm'].valueChanges.subscribe(weekFilter => {
      // we dispatch only if the wee has been given
      if (weekFilter.week) {
        this.store.dispatch(
          new filterActions.FilterByWeek({
            byWeek: {
              year: weekFilter.year,
              week: weekFilter.week
            }
          })
        );
      } else {
        // else means that week is empty in the input field, so we reload
        this.store.dispatch(new mapActions.Load());
      }
    });

This means if I have 10 input fields for filtering I have to duplicate this code for each filter and subscribing to valueChanges?

Is there a more elegant way to dispatch an action when a value of the form changes?

Closing as non-actionable

@fxck @MrWolfZ can you provide your input on this discussion after 2 years now, still i could not see any solid reference or best practice to use

I've been using @MrWolfZ's lib for a while now, wrote a layer around it

image

it takes care of registering the form to a global slice of the ngrx state, has all the observable state of the form on it, along with helpers that return actions for you to dispatch, this part is basically a facade

image

All in all, it works fine, has very similar to straightforward APIs that reactive forms have, but with the advantage of being able to change the state fully by dispatching actions and reading the state from ngrx store, it's little hacky inside, especially the main reducer, but works in all the cases I needed (including validations, focus management etc), never had the resources to make something community usable out of it though.

@fxck what u suggest to the community, is it ngrx/forms or any other idea which can help others also, or it would be great if u could write some article giving a brief idea about your work. as i could see u do have great knowledge related to this issue and u are the early bird of this discussion

It's hard, angular reactive forms suck, no matter if they make them typed or not, but ngrx-forms are extremely low level, too much for a widespread adoption. So given that ngrx team is not quite willing to take (any) forms project under their wings, I don't have a suggestion for you.

angular reactive forms suck just for my personal interest - can you please elaborate a little?

read this issuue, discussion prior to this issue
https://github.com/ngrx/core/issues/12#issuecomment-273470234 or some of the 300 open issues or this proposal that summarize some of the flaws

amongst other things

  • it's not truly reactive (missing reactive states for like half a things)
  • it's nearly impossible to properly reset (submitted state is on ngForm directive)
  • it's not type
  • it doesn't play well with ngrx ecosystem (try reseting form from your effects)

the good thing is, that form value accessor is pretty extendable, I don't have any compatibility issue with any third party components while using ngrx-forms, so if someone truly wanted to make an alternative, it's certainly possible

We were also using ngrx-forms on project with around 2000 forms, and tables. Some of the forms were simple with 1-10 fields, some of them were "components" used as parts of bigger forms, some of them were complex forms with lot of synchronous and asynchronous business logic, and we had also 2 complex 1000+ fields configurators. At the beginning we tried angular-forms, but it was too "closed" to fit our needs. We appreciated the "low-level" of ngrx-forms.

We had to solve other problems, that ngrx-forms is not trying to solve (or was not trying to solve 2 years ago):

  • Registering, and unregistering form-states into global state. It was a bit more complicated, because form identifier had to be calculated in runtime.
  • Cooperating ngrx-forms with ag-Grid, because a lot of tables were "editable" tables.
  • We added a lot of custom metadata into state for some special form controls and because of use of ag-Grid.
  • We did not like the @Effects - it was too simple, so we made separate layer for all asynchronous code and API to read and write to forms, and listen on form changes.
  • We removed boxing/unboxing.
  • We wanted making reducers to be more simple. So we have changed the ngrx-forms way (interface -> initial value -> update functions -> initial state -> reducer) to more simple syntax:
    ts this.form = this.formServiceFactory.create({ id: ...., definition: defineGroup().addControls({ userName: defineStringControl('User's login:', { update: validate(required, maxLength(40), minLength(5)), }), email: defineStringControl('User\'s email:', { create: setReadonly(true), update: validate(required), }), emailValidated: defineBooleanControl('Email validated', { defaultValue: false, }) }, { update: state => { const emailReadonly = state.controls.userName.isValid === false; return setReadonly(emailReadonly, state, state.controls.email); }, }), })
    Thus type of form is not resolved from interface, but from complex function, and so we had no problems with boxing/unboxing.
  • Logic common to several controls is programmed in the update function of their common parent. The update function can only see and change the state of self and of its children.
  • We are controlling reducer's "stability" - the reducer is executed several times and if the state always change, we throw exception to developer.

What I am trying to say - we did a lot of complex things with ngrx-forms, but we were never blocked by ngrx-forms. It was always possible to modify ngrx-forms to suit our problems. This would be never possible with angular forms. And we are still happy with debugging the redux state in redux dev tools. The problems were with debuging huge states - so we had to do some optimalization so it is now usable, but copying big state from browser to redux dev tools is a bottle neck somtimes.

Also, at the end our modification of ngrx-forms was ok for junior programmers, because we have simplified the api for create/update state, and also because we created other layer to access form from "outside" reducer. We dont let application programmers to directly send messages into state.

So for me - ngrx-forms was perfect for complicated project, and I would appreceate if ngrx-forms would be a community project, so it can grow to perfect form library.

Was this page helpful?
0 / 5 - 0 ratings