briebug / ngrx-auto-entity

NgRx Auto-Entity: Simplifying Reactive State
https://briebug.gitbook.io/ngrx-auto-entity/
Other
66 stars 12 forks source link

Async validation #205

Closed RBleyenberg closed 2 years ago

RBleyenberg commented 2 years ago

Question...

Without ngrx-auto-entity i'm able to implement the async form validation as follow;

private existTitle(): AsyncValidatorFn { return (control: AbstractControl): Promise<{ [key: string]: any } | null> | Observable<{ [key: string]: any } | null> => { const invalid = control.value; return this.store.select(TitleSelector.getAllAbbrev, { abbrev: invalid}).pipe( debounceTime(500), take(1), map(value => { return value.includes(invalid) ? { invalid: true } : null; }) ) }; }

and the selector is then;

export const getAllAbbrev = createSelector( selectAllTitles, (titles) => titles.map(titles => titles.abbrev) );

when i'm using auto-entity the store is different from products to product (redux devtools)

So when i'm using the facade all$ it only gives back the single entity (used on the single product page).

Short idea of my question is;

How can we use a async validator within a reactive form that makes use of the proper selector (facade) in order to select all product.name from the product details page in order to use it within the async validator

Thanks upfront for any help given.

jrista commented 2 years ago

Hi @RBleyenberg. So, with Auto-Entity, you are not required to use the Facades. The facades are there as a convenience if you are interested in using facades, but they are just an option. We provide all of our selectors to the developer through the buildState functions. So if you want to build your own custom selectors, you can, and it is very easy to do.

When calling buildState for an auto-entity state, just specify the selectors you wish to use:

export const {
  facade: ProductsFacadeBase,
  selectors: {
    selectAll: allProducts
  }
} = buildState(Product);

Once you have one of the built-in selectors, you are then free to create your own selectors that compose the built-in selectors:

export const allProductNames = createSelector(
  allProducts,
  (products: Product[]) => products.map(product => product.name)
);

Once you have your custom selector, you can either use store.select to use it directly, or you could add it to your facade if you wished:

export class ProductsFacade extends ProductsFacadeBase {
  allNames$: Observable<string> = this.store.select(allProductNames);  

  // constructor
}

You can then use either just the Store, or your custom facade, to build out your custom validators. For more information, you can check out the documentation here:

https://briebug.gitbook.io/ngrx-auto-entity/advanced/usage/building-state/buildstate-func https://briebug.gitbook.io/ngrx-auto-entity/advanced/usage/building-state/selector-map https://briebug.gitbook.io/ngrx-auto-entity/advanced/usage/custom-selectors

RBleyenberg commented 2 years ago

awesome... thx for this great answer \o/