Giter Club home page Giter Club logo

store's Introduction


NGXS is a state management pattern + library for Angular



Quick Links


The Goal of NGXS

NGXS tries to make things as simple and accessible as possible. There can be a lot of boilerplate code in state management, thus a main goal of NGXS is to reduce boilerplate allowing you to do more things with less. It is also not necessary to be super familiar with RxJs.

The Goal of NGXS Labs

The idea with this github organisation is to provide a place for the community to create libraries that augment the main framework with functionality that does not need to be integrated directly into the framework and therefore can evolve through their initial iterations of experimentation without affecting the main @ngxs/store library.

Getting Started - Local Development

Installation

To get started locally, follow these instructions:

  1. If you haven't done it already, make a fork of this repo.
  2. Clone to your local computer using git.
  3. Make sure that you have installed NodeJS.
  4. Make sure that you have yarn installed.
  5. Run yarn install.
  6. Run yarn build:packages.

Creating new packages or add feature/fix

if you make changes @ngxs/store
  1. Run development mode yarn build:packages --package store --watch
  2. Run serve integration examples yarn start
  3. ...development...
  4. Run tests yarn test:ci
  5. Create pull request
if you add a new package @ngxs/my-super-plugin
  1. Create a new project folder packages/my-super-plugin
  2. Create template library with ngPackagr
  3. Add your project to package.json
  4. Run development mode yarn build:packages --package my-super-plugin --watch
  5. ...development...
  6. Run build yarn build:packages --package my-super-plugin
  7. Run tests yarn test:ci
  8. Create pull request

NGXS Labs

If you have ideas for creating unique libraries, you can join us. Email us at [email protected]. Or you can email us on Twitter or Slack.

Packages

Tools

Project Package Version Links
NGXS CLI @ngxs/cli latest README
NGXS Schematics @ngxs/schematics latest README

Packages

Project Package Version Links
NGXS Store @ngxs/store latest README snapshot
NGXS Logger-plugin @ngxs/logger-plugin latest README snapshot
NGXS Devtools-plugin @ngxs/devtools-plugin latest README snapshot
NGXS WebSocket-plugin @ngxs/websocket-plugin latest README snapshot
NGXS Form-plugin @ngxs/form-plugin latest README snapshot
NGXS Router-plugin @ngxs/router-plugin latest README snapshot
NGXS Storage-plugin @ngxs/storage-plugin latest README snapshot
NGXS HMR @ngxs/hmr-plugin latest README snapshot

NGXS Labs

Project Package Version Links
NGXS-labs Data @ngxs-labs/data latest README
NGXS-labs Emitter @ngxs-labs/emitter latest README
NGXS-labs Immer adapter @ngxs-labs/immer-adapter latest README
NGXS-labs Dispatch decorator @ngxs-labs/dispatch-decorator latest README
NGXS-labs Select snapshot decorator @ngxs-labs/select-snapshot latest README
NGXS-labs Async storage plugin @ngxs-labs/async-storage-plugin latest README
NGXS-labs Entity state @ngxs-labs/entity-state latest README
NGXS-labs Testing tools @ngxs-labs/testing latest README
NGXS-labs Actions Executing @ngxs-labs/actions-executing latest README
NGXS-labs Attach Action @ngxs-labs/attach-action latest README

Community

Project Package Version Links
Reset Plugin ngxs-reset-plugin latest README
NGXS-Loading-plugin ngxs-loading-plugin latest README
NGXS-History-plugin ngxs-history-plugin latest README

Contributors

Thanks to all our contributors!

store's People

Contributors

amcdnl avatar armanozak avatar arturovt avatar carniatto avatar deebloo avatar dmitry-stepanenko avatar eranshmil avatar estrellajm avatar eysikal avatar greenkeeper[bot] avatar herkulano avatar joaqcid avatar juliusstoerrle avatar juracy avatar jvandemo avatar leon avatar maartentibau avatar markwhitfeld avatar mobilerast avatar oanasurdea avatar profanis avatar renovate-bot avatar renovate[bot] avatar rfprod avatar sa-bangash avatar sebholstein avatar splincode avatar tsawan avatar uberspeck avatar yoglib avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

store's Issues

Ngxs Service Rename

I personally don't love this naming:

constructor(private ngxs: Ngxs) {
   this.ngxs.dispatch(...);
}

I'd like to make it Store name but then that would conflict with the @Store() decorator. Anyone got any ideas?

Where should @Mutations live in a multi-module application

Hi,
According to your style guide events can be in a separate folder from the store folder.

Given,
import { Store, Mutation } from 'ngxs';

@Store({
defaults: {
feed: false,
animals: []
}
})
export class ZooStore {
@mutation(FeedAnimals)
feedAnimals(state, { payload }) {
state.feed = true;
}
}

Where do you recommend mutations live? In an enterprise level application with different modules, the ZooStore can be cluttered quite rapidly if all Mutations live in the Store class.

Cheer

Subscriber not called after action dispatch

Component

logout() {
	this.ngxs.dispatch(new Logout()).subscribe(() => {
		this.router.navigate(['']); // <-- This code never runs
	});
}

Store

@Action(Logout)
logout() {
	this.loginService.logout();
}

Lazy Loading Issues

When you lazy load it causes the state to be overridden because of DI overlap.

UglifyJS breaking ngxs?

I used to build my app for prod with ng build --app=default -oh=media --prod but the ngxs store is not working with prod builds with this command, ngxs works without issues in dev modeng s -e mock --extract-css --preserve-symlinks --proxy-config proxy.conf.js

After trying various -prod mode options, I am thinking UglifyJS is causing this issue.

unfranaltiy angular-cli doesn't have option to desable UglifyJS with -prod builds.
As a workaround, I am using following command to emulate prod builds.
ng build --app=default -oh=media -e prod --aot=true --build-optimizer=true --named-chunks=false --sourcemaps=false (this cannot add service-worker unfraunalty)

wonder if anyone experiencing this issue when building for prod with angular-cli!

Sub Stores

Ability to create stores within stores. https://gist.github.com/amcdnl/6998c0dbad7af5f424dc7719527f9fb8

One idea is to create dot notation with store names like:

@Store({
   name: 'cart'
})
export class CartStore{}

@Store({
   name: 'cart.items'
})
export class CartItemsStore {}

then you hook it up like:

@NgModule({
   imports: [
      NgxsModule.forRoot([CartStore, CartItemsStore])
   ]
})
export class MyModule {}

Store has already been added app

Currently I have 2 stores, AppStore and AuthStore. AppStore is controlled by the AppModule for general all-purpose states for the app. AuthStore is managed by the AuthModule.

In AppModule:

  imports: [
    //...
    NgxsModule.forRoot([AppStore]),
    AuthModule,
    // ...
  ]

In AuthModule:

  imports: [
    //...
    NgxsModule.forFeature([AuthStore]),
    AuthModule,
    // ...
  ]

If I do this in AuthModule, I get an error:

Error: Store has already been added app
at _loop_1 (ngxs-api.js:77)
at StoreFactory.add (ngxs-api.js:98)
at StoreFactory.addAndReturnDefaults (ngxs-api.js:114)
at NgxsFeatureModule.initStores (ngxs-api.js:455)
at new NgxsFeatureModule (ngxs-api.js:451)
at _createClass (core.js:10895)
at createProviderInstance$1 (core.js:10865)
at initNgModule (core.js:10818)
at new NgModuleRef
(core.js:12073)
at createNgModuleRef (core.js:12062)

AuthModule isn't LazyLoaded. If I removed the import from AuthModule and add the AuthStore to the import in AppModule it works. I'd rather not add the AuthStore into the AppModule if I can help it.

Am I not doing this correctly? Does forFeature() only work if the module is lazy loaded?

Redux Middleware Adapter

Create a adapter that will allow redux middleware to be compat. Should be easy, just mapping the signatures.

Ability to rehydrate state from storage to support multi-tab applications (browsers)

[x] Feature Request

User login to our app then opens a second tab and continues. Later on, logs out from the active tab. All other tabs will remain in the dark as their state is not updated.

How about we do something to rehydrate peer states when persisted storage (session) changes.

Example from NGRX.

// actions
export enum AuthActionTypes {
  AuthMultiTabSyncRequest = '[AUTH]: Multi-tab Sync Refresh' // multi-tab session support
}
export class MultiTabSyncRequest implements Action {
  readonly type = AuthActionTypes.AuthMultiTabSyncRequest;
  constructor(public payload: string) {}
}
sync(payload: string) {
  this.store.dispatch(new MultiTabSyncRequest(payload));
}
// reducer
export function authMetaReducer(reducer: (state: AuthState, action: AuthActions) => any) {
  const storageEngine = localStorage
  const storageKey = 'session';
  return function(state, action) {
    if (
      state == undefined ||
      (action.type === AuthActionTypes.AuthMultiTabSyncRequest &&
        action.payload.token === storageKey)
    ) {
      const persistedState = storageEngine.getItem(storageKey);
      return persistedState ? JSON.parse(persistedState) : reducer(state, action);
    }
    const nextState = reducer(state, action);
    if (state.status.signature !== nextState.status.signature) {
      storageEngine.setItem(storageKey, JSON.stringify(nextState));
    }
    return nextState;
  };
}
 // authService
  private enableStorageEvents() {
    if (this.options.storage) {
      this.options.storage.eventListener(
        'storage',
        event => {
          this.action.sync(event.key);
        },
        false
      );
    }
  }

The storage plugin may be the best place for this.

Schematics

According to the docs we should generate three files.

todos.store.ts
todos.store.spec.ts
todos.events.ts

This could also look for the closest module and automatically add the store as a declaration and use it in the forRoot or forFeature functions.

How to update state correctly

The dev-tool scrrenshot below reflects my store:

dev-tool

Here are the mutations:

@Store(
    {
      defaults: new Rs()
    } )
export class RsStore {
 @Mutation( AddRsRosPainUi )
  addPainUi( state, { payload } ) {
    state.ros.ui.pain = payload
  }
  
  @Mutation( InitRsRosPainUi )
  initRsRosPainUi( state, { payload } ) {
    state.ros.ui.pain = new FormState()
  }
  
  @Mutation( ReInitRsRosPainUi )
  reInitPainUi( state, { payload } ) {
    state.ros.ui.pain = payload
  }
  
  @Mutation( UpdateRsRosPainUi )
  updatePainUi( state, { payload } ) {
    state.ros.ui.pain = payload
  }
}

@Store(
    {
      defaults: new Git()
    } )
export class GitStore {

  @Mutation( AddGitRosPainUi )
  addPainUi( state, { payload } ) {
    state.ros.ui.pain = payload
  }
  
  @Mutation( InitGitRosPainUi )
  initGitRosPainUi( state, { payload } ) {
    state.ros.ui.pain = new FormState()
  }
  
  @Mutation( ReInitGitRosPainUi )
  reInitPainUi( state, { payload } ) {
    state.ros.ui.pain = payload
  }
  
  @Mutation( UpdateGitRosPainUi )
  updatePainUi( state, { payload } ) {
    state.ros.ui.pain = payload
  }
 
}

Both store updates, but although there are two instances of the PainComponent, the updates are the same.

Question:

  1. For the RsStore, I expect the the payload assignments to be

state.rs.ros.ui.pain = payload

and for the GitStore

state.git.ros.ui.pain = payload

However, neither updates the store.
Could you say why is this?. I think this is why both mutations updates both pain references in the store.
2. What other ways could I use to drill-down to the pain property in each store?

Cheers

Make @Select decorator generic for type safety when selecting from a store

It would be great if the @Select could be made generic so we can have type safety when selecting from a store.

Something like this would then be possible:

  @Select<LayoutStore>(state => state.sidenavOpen) <--- type safety for the selectable state
  sidenavOpen$: Observable<boolean>;

Would that be possible?

Merge Action and Mutation

ATM if you want to do anything async you need to use both and Action and Mutation where the Action will return a new event that triggers a mutation. To me this seems like an unnecessary step. Ngxs already has the ability to handle returning either a raw value, Observable or Promise so I propose we just have Action and that instead of returning an event an action method just returns the new state.

The proposed API would look something like this. Notice that the action methods always resolve in the new state. There are some situations I want to make sure this can handle but thought it would be a good place to start the discussion. One of the things that I would want to solve for is being notified when a particular action is complete. My initial thought is the dispatch method could return an observable that resolves when the action is complete

screen shot 2018-03-06 at 10 34 46 pm

Select Combinations

Add ability to combine selects via decorators:

@Select(
   {  foo: 'foo.bar', bar: (state) => state.bar },
   (({ foo, bar }) => foo.filter(f => f !== bar)))
bars: Observable<Bar>;

creating feature stores

Hi,
I have a clerking and a registration feature.

// clerking
import { Store } from 'ngxs';

@Store({
defaults: {
feed: false,
animals: []
}
})
export class ClerkingStore {}

// registration
import { Store } from 'ngxs';

@Store({
defaults: {
present: false,
noShow: false
}
})
export class RegistrationStore {}

What do I need to do to create feature stores instead of a single store.

Maybe you could include it in the documentation under the subheading 'Creating Feature Store'

Thanks

Allow select typed ?

Is there a way to pass the state type to Select?

// Also accepts a function like our select method
@Select(state => state.animals) animals$: Observable<string[]>;
as
@Select(state<StateType> => state.animals) animals$: Observable<string[]>;

Benefit?

Hey!
Flying over the Code, but dont see the benefit over ngrx
If there is any could you please explain what the benefits are?

LoggerPluginModule giving error

I am trying to use LoggerPluginModule and it works ok as long as I have a single store. Once I add a 2nd store, I start getting the following error (Windows, Angular 5) in both Chrome and IE. Here I've added a second store "WellStore" and it's giving error.

image001

Custom localStorage options

[x] enhancement

Allow localStorage to be passed in as an option.

This is great for the mobile environments (native script) where there is no localStorage.

Any option that provides setItem() and getItem() should do.

Type Safety

There are several parts of the library that open the user up to potential mistakes that SHOULD be caught by the compiler. An example of this is the Select decorator and the fact that the Ngxs class isn't generic so the select method cannot be typed. Anything where you pass in a string (like the selectors) are an opening for potential mistakes

bug: Action, LazyLoadedModule and LoggerPluginModule

Hello, there is a bug occuring with actions on lazy loaded modules, but only when LoggerPluginModule is imported.

I have tried to make the example as simple as possible :
The button dispatches an event which is watched by an action.
The action simply dispatches an event which is watched by a mutation.

Stackblitz example :
https://stackblitz.com/edit/ngxs-lazy-loaded-module?file=main.ts

Repro steps :
Navigate to the lazy loaded module by clicking on the "toggle component" button
Clicking the "Toggle visibility" button raises an error (action managed on ToggleStore imported with forFeature).

If we remove the LoggerPluginModule import, everything works fine.

@Select() should accept a store class

Since a class with @Store has the "name" metadata attached to it we should be able to use the class as a selector. I think this helps cleanup the basic use case and keep folks from having to keep track of store names themselves.

class MyComponent() {
  @Select(MyStore) data: Observable<DataModel>;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.