Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚀[FEATURE]: @ngxs/storage-plugin forFeature #850

Closed
Carniatto opened this issue Feb 18, 2019 · 19 comments
Closed

🚀[FEATURE]: @ngxs/storage-plugin forFeature #850

Carniatto opened this issue Feb 18, 2019 · 19 comments

Comments

@Carniatto
Copy link
Contributor

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Performance issue
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => https://github.com/ngxs/store/blob/master/CONTRIBUTING.md
[ ] Other... Please describe:

Current behavior

only supports forRoot option

Expected behavior

allow only part of the state to be persisted in localStorage

What is the motivation / use case for changing the behavior?

In large applications or even in Nx Workspaces one's might find interesting to have the state for some lazy modules persisted in localStorage but not all the state

Environment


Libs:
- @angular/core version: 7.1.2
- @ngxs/store version: 3.3.4


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
 
For Tooling issues:
- Node version: v11.4.0
- Platform:  OSx Mojave

@splincode
Copy link
Member

Can in more detail

@eranshmil
Copy link
Member

eranshmil commented Feb 18, 2019

You can use the key option from the forRoot. For example:
state.sub.key

@Carniatto
Copy link
Contributor Author

@eranshmil I don't see this working, can you provide me an example?

@splincode My use case is when you have a root state and couple of lazy loaded states but you only wanna save in storage one of the lazy loaded states.

@drakenfly
Copy link

I thought about the same thing. What @Carniatto wanted to say with "allow only part of the state to be persisted in localStorage" is (at least it was like following in my opinion): Allow to add some keys with a forFeature dynamically, based on the lazy loaded modules.

For example, if you split your application like this:

  • AppModule
    |-- AdminModule (lazy module, canLoad and canActivate to prevent unauthorized access)
    |-- CustomerModule (lazy module)

Then I'd personally don't like to configure the NgxsStorage-plugin for AdminModule when loading AppModule initially.

@kxc0re
Copy link

kxc0re commented Oct 2, 2019

it's also a performance gain since the filtering for keys happens after a storage-update has been initiated

https://stackblitz.com/edit/ngxs-repro-yffmsq
setItem gets called with unchanged values, when the unwatched stateSlice changes

@arturovt arturovt self-assigned this Oct 13, 2019
@arturovt arturovt removed their assignment Oct 23, 2019
@splincode splincode changed the title feat: @ngxs/storage-plugin forFeature 🚀[FEATURE]: @ngxs/storage-plugin forFeature Nov 4, 2019
@splincode
Copy link
Member

@Jordan-Hall
Copy link

@splincode Only issue with using data would be the fact you are removing CRQS. For me it's not a benefit. I hate to see this just replace all over and go like NGRX

@splincode
Copy link
Member

@Jordan-Hall up to you, if NGRX can help you

@Jordan-Hall
Copy link

I think you've missed understood. I'm saying this is required and not to force NGXS data on us because I hate NGRX. One of the reasons why I've been moving clients over to NGXS

@splincode
Copy link
Member

Therefore, this issue is still open, and it must be solved. And if you have the time and desire, you can send a pull request and it will be a good help

@Jordan-Hall
Copy link

Sure, doesn't it make sense to decouple that one in @ngxs-labs/data? It appears to have better API rather than using ForRoot and forFeature. Plus then Data can use it

@splincode
Copy link
Member

Using the date plugin, you do not need forRoot, forFeature. Because there you can add a decorator over the state and it will be easily applied.

@hobe
Copy link

hobe commented Feb 22, 2022

I managed to add an additional key in a lazy loaded module (and do not provide it in the "main" module) with the following workaround:

I've placed the code in an canActivate Guard that is attached to the lazy loaded module route (not quite sure if this could also be placed in the lazy loaded Module constructor):

export const MFEAPP_STATE_NAME = 'mycustomappstatename';

@State<MFEAppStateModel>({
  name: MFEAPP_STATE_NAME ,
...
}

In order to update the keys, I inject the NGXS_STORAGE_PLUGIN_OPTIONS and update the string array manually:

export class MFEAppSettingsGuard implements CanActivate {
  constructor(
    @Inject(NGXS_STORAGE_PLUGIN_OPTIONS)
    private readonly ngxsStoragePluginOptions: NgxsStoragePluginOptions
  ) {
    this.ngxsStoragePluginOptions.key = [
      ...(this.ngxsStoragePluginOptions.key as string[]),
      MFEAPP_STATE_NAME,
    ];
  }
  public canActivate(): Observable<boolean> {...}`

@arndwestermann
Copy link

@hobe

Just tested it in the constructor of the lazy loaded module and it seems to work. Thanks for your workaround!

@arndwestermann
Copy link

@hobe

I was a bit premature when I commented. The key is created in the local storage, but when I reload the value is reset to the initial state. Do you also had this problem and if so how did u resolve it?

@luchian94
Copy link

I tried @hobe approach but it doesn't work for me.

Seems like the problem is that even if you update plugin options the internal keys variable used by plugin remains with initial value assigned inside the constructor.

image

@arturovt
Copy link
Member

@luchian94 I did consider to implement this feature and I think it should be a part of the implementation. The problem is the design and the order of things happening in the code.

Suppose the following case:

imports: [
  NgxsModule.forFeature([CountriesState]),
  NgxsStoragePluginModule.forFeature([CountriesState])
]

The NgxsModule (provided as ngModule in forFeature) will be created before the module provided in NgxsStoragePluginModule.forFeature. Which means the plugin handle() will run earlier before keys are updated to contain the CountriesState.

We can't force users to declare the NgxsModule after the storage plugin module because the behavior won't be determenistic.

@prawin-s
Copy link

prawin-s commented Jul 5, 2023

Any update on this issue?

@arturovt
Copy link
Member

Great news! v18.0.0 has been released and it includes a fix for this issue.
We are closing this issue, but please re-open it if the issue is not resolved.
Please leave a comment in the #2173 if you come across any regressions with respect to your issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests