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

Add observables via select() #12

Merged
merged 3 commits into from
May 2, 2016

Conversation

micha149
Copy link
Contributor

Currently I am missing the ability to work with observables on the store. This is a nice feature which is currently implemented in ngrx/store, but I like the idea to just wrap the actual redux library. So I implemented the select() function from ngrx/strore and this comes with this pull request.

The idea is simply call select() on the store an pass a key or a selector function which extracts the required informations from the store. The method returns an observable which only emit data if the value, returned by the selector, changes.

export class AppComponent implements OnInit {

    constructor(private store: AppStore) {
    }

    ngOnInit() {
        // selects counter property from store
        this.counter$ = this.store.select('counter');

        // selects deep nested information from a immutable.js map
        this.foo$ = this.store.select(state => state.getIn(['foo', 'bar' 'counter']));
    }

    // ...
}

The ability to pass a selector function enables cool possibilities like passing memoized selector functions from reselect:

import { createSelector } from 'reselect';

const getVisibilityFilter = (state) => state.visibilityFilter
const getTodos = (state) => state.todos

const getVisibleTodos = createSelector(
    [ getVisibilityFilter, getTodos ],
    (visibilityFilter, todos) => {
        switch (visibilityFilter) {
            case 'SHOW_ALL':
                return todos
            case 'SHOW_COMPLETED':
                return todos.filter(t => t.completed)
            case 'SHOW_ACTIVE':
                return todos.filter(t => !t.completed)
        }
    }
)

@Component({
    // ...
})
export class MyComponent implements OnInit {

    constructor(private store: AppStore) {
    }

    ngOnInit() {
        // selects counter property from store
        this.todos$ = this.store.select(getVisibleTodos);
    }

    // ...
}

Observables are a key feature for performant large scale angular2 apps.
This commits forks the select() function from ngrx/store, so we are able
to retrieve a observable for a particular state property.
@rubyboy
Copy link
Contributor

rubyboy commented Apr 21, 2016

@micha149 this is an awesome PR and a very welcome addition to the angular2-redux library.
I hope you don't mind if I linger with merging it for a bit. I'm a bit busy in the next week and I would like to review the code thoroughly before merging. I do love the idea and hopefully would find the time in the next week or so to pull it.

BTW, have you seen reduxjs/redux#1632 ?
Maybe we can update the Redux dependency to 3.5.1 as part of this PR? Would that change your implementation in any way, given that Redux now support RxJS as part of its own subscription model?

@micha149
Copy link
Contributor Author

@rubyboy oh, didn't see that. I updated the pull request. I could drop 2 lines of code and use Observable.from(store) instead… Thanks for the hint.

@micha149
Copy link
Contributor Author

By the way… sorry for the failing CI build. But I can not figure out whats the problem. Tests passes, no linting errors… only typing problems which are also in a working build on master. Do somebody know what the problem is?

@rubyboy rubyboy merged commit 1e14697 into InfomediaLtd:master May 2, 2016
@rubyboy
Copy link
Contributor

rubyboy commented May 2, 2016

Sorry it took me a while to merge. I'll update the project now to latest angular+redux and release a new version to NPM

@rubyboy
Copy link
Contributor

rubyboy commented May 2, 2016

@micha149 I noticed that the "select" method doesn't work when the dev tools extension is enabled (https://github.com/zalmoxisus/redux-devtools-extension).
Are you able to take a look?

You can see that by adding the following line into the AppComponent of the example app in the project:

      appStore.select((state)=>state).subscribe((state)=>console.log(state));
      // this won't work. Looking at the object outputted above shows why
      appStore.select("counter").subscribe((counter)=>console.log("counter",counter));

You need to have the extension installed (otherwise, it won't enable it)

@rubyboy
Copy link
Contributor

rubyboy commented May 2, 2016

Created the following issue so it's tracked properly: #13

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

Successfully merging this pull request may close these issues.

2 participants