Skip to content

Instantly share code, notes, and snippets.

@dbashford
Last active September 15, 2017 19:01
Show Gist options
  • Save dbashford/ed374d5dc78247a962dfcd98f3dcae6e to your computer and use it in GitHub Desktop.
Save dbashford/ed374d5dc78247a962dfcd98f3dcae6e to your computer and use it in GitHub Desktop.
AFTER-Ember-Redux
import * as ACTION_TYPES from 'twiddle/actions/types';
import {
previousPageNumber,
nextPageNumber,
lastPageNumber
} from 'twiddle/reducers/selectors';
export const updatePageSize = (newPageSize) => ({
type: ACTION_TYPES.SET_PAGE_SIZE,
payload: newPageSize
});
const _goToPage = (pageNumber) => ({
type: ACTION_TYPES.SET_PAGE,
payload: pageNumber
});
const _pager = (selector) => {
return (dispatch, getState) => {
const pageNumber = selector(getState());
dispatch(_goToPage(pageNumber));
};
};
export const firstPage = () => _goToPage(1);
export const nextPage = () => _pager(nextPageNumber);
export const previousPage = () => _pager(previousPageNumber);
export const lastPage = () => _pager(lastPageNumber);
export const SET_PAGE = 'TWIDDLE::SET_PAGE';
export const SET_PAGE_SIZE = 'TWIDDLE::SET_PAGE_SIZE';
import Ember from 'ember';
import { connect } from 'ember-redux';
import { itemsToRender } from 'twiddle/reducers/selectors';
const stateToComputed = (state) => ({
itemsToRender: itemsToRender(state)
});
const ItemsComponent = Ember.Component.extend({});
export default connect(stateToComputed)(ItemsComponent);
import Ember from 'ember';
import { connect } from 'ember-redux';
import {
firstPage,
previousPage,
nextPage,
lastPage
} from 'twiddle/actions';
import {
isFirstPage,
isLastPage,
} from 'twiddle/reducers/selectors';
const stateToComputed = (state) => ({
isLastPage: isLastPage(state),
isFirstPage: isFirstPage(state)
});
const dispatchToActions = {
firstPage,
previousPage,
nextPage,
lastPage
};
const PagerComponent = Ember.Component.extend({});
export default connect(stateToComputed, dispatchToActions)(PagerComponent);
import Ember from 'ember';
import { connect } from 'ember-redux';
import { updatePageSize } from 'twiddle/actions';
const PAGE_SIZES = [25, 50, 100];
const stateToComputed = ({ page: { pageSize } }) => ({
pageSize
});
const dispatchToActions = {
updatePageSize
};
const PageSizer = Ember.Component.extend({
pageSizes: Ember.computed('pageSize', function() {
const pageSize = this.get('pageSize');
return PAGE_SIZES.map((size) => {
return {
size,
selected: size === pageSize
}
});
}),
actions: {
// proxy action to convert to int
pageSizeSelected(pageSize) {
this.send('updatePageSize', parseInt(pageSize, 10));
}
}
});
export default connect(stateToComputed, dispatchToActions)(PageSizer);
import Ember from 'ember';
import { connect } from 'ember-redux';
import {
beginPageIndex,
endPageIndex,
numberOfItems
} from 'twiddle/reducers/selectors';
const stateToComputed = (state) => ({
beginPageIndex: beginPageIndex(state),
endPageIndex: endPageIndex(state),
numberItems: numberOfItems(state)
});
const PagerStatusComponent = Ember.Component.extend({});
export default connect(stateToComputed)(PagerStatusComponent);
import Ember from 'ember';
export default Ember.Controller.extend({
appName: 'Ember Twiddle'
});
import { combineReducers } from 'redux';
import { handleActions } from 'redux-actions';
import * as ACTION_TYPES from 'twiddle/actions/types';
const initialState = {
pageNumber: 1,
pageSize: 25,
items: Array.from({length: 127}, () => Math.floor(Math.random() * 1000))
};
const page = handleActions({
[ACTION_TYPES.SET_PAGE]: (state, { payload }) => {
return Object.assign({}, state, { pageNumber: payload});
},
[ACTION_TYPES.SET_PAGE_SIZE]: (state, { payload }) => {
return Object.assign({}, state, { pageSize: payload});
}
}, initialState);
export default combineReducers({
page
});
import reselect from 'reselect';
const { createSelector } = reselect;
const pageNumber = (state) => state.page.pageNumber;
const pageSize = (state) => state.page.pageSize;
const items = (state) => state.page.items;
export const numberOfItems = createSelector(
items,
(items) => (items || []).length
);
export const isFirstPage = createSelector(
pageNumber,
(pageNumber) => pageNumber === 1
);
export const previousPageNumber = createSelector(
isFirstPage,
pageNumber,
(isFirstPage) => {
return isFirstPage ? 1 : pageNumber - 1;
}
);
export const lastPageNumber = createSelector(
pageSize,
numberOfItems,
(pageSize, numberOfItems) => Math.ceil(numberOfItems / pageSize)
);
export const nextPageNumber = createSelector(
pageNumber,
lastPageNumber,
(pageNumber, lastPageNumber) => Math.min(pageNumber + 1, lastPageNumber)
);
export const isLastPage = createSelector(
pageNumber,
lastPageNumber,
(pageNumber, lastPageNumber) => pageNumber === lastPageNumber
);
export const beginPageIndex = createSelector(
pageNumber,
pageSize,
(pageNumber, pageSize) => (pageNumber - 1) * pageSize + 1
);
export const endPageIndex = createSelector(
beginPageIndex,
pageSize,
numberOfItems,
(beginPageIndex, pageSize, numberOfItems) => {
const calculatedPage = beginPageIndex + pageSize - 1;
return Math.min(calculatedPage, numberOfItems);
}
);
export const itemsToRender = createSelector(
items,
beginPageIndex,
endPageIndex,
(items, beginPageIndex, endPageIndex) => items.slice(beginPageIndex - 1, endPageIndex)
);
{{pager-status}}
{{items-display}}
{{page-changer}}
{{page-sizer}}
<ul>
{{#each itemsToRender as |item|}}
<li>{{item}}</li>
{{/each}}
</ul>
{{#unless isFirstPage}}
<a href='' {{action 'firstPage'}}>First</a>
<a href='' {{action 'previousPage'}}>Prev</a>
{{/unless}}
{{#unless isLastPage}}
<a href='' {{action 'nextPage'}}>Next</a>
<a href='' {{action 'lastPage'}}>Last</a>
{{/unless}}
<select onchange={{action 'pageSizeSelected' value="target.value"}}>
{{#each pageSizes as |pS|}}
<option value={{pS.size}} selected={{pS.selected}}>{{pS.size}}</option>
{{/each}}
</select>
Viewing {{beginPageIndex}} to {{endPageIndex}} of {{numberItems}}
{
"version": "0.12.1",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.12.0",
"ember-template-compiler": "2.12.0",
"ember-testing": "2.12.0"
},
"addons": {
"ember-redux": "3.0.0",
"ember-redux-actions": "0.3.0",
"ember-reselect-shim": "2.0.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment