- Add this repo as a git submodule in the
/packagesrepository $ meteor add lef:adminlist- Make sure the following icons are in your fontawesome library:
faCheck, faEdit, faSearch, faSort, faSortAlphaDown, faSortAlphaUp, faSpinner, faTimes
(Using an icons helper file* is recommended.)
Use the <List /> component to create a list of data with filter, pagination and sorting functions.
importListfrom'meteor/lef:adminlist'importCollectionfrom'./somewhere'// fields directly shown as columnsconstfields=['name','emails.0.address','imageField']// subset of columns shown below sm (or folded panel in @lefapps/admin-dashboard)constfieldsCompact=['name','score']consttitles=['Name','Email Address','Profile image']// link (recommended)constedit={action: doc=>`${this.props.match.url}/edit/${doc._id}`,type: 'link'}// component (listProps exposes default children (icon), className)constedit={action: ({°id, listProps })=><Linkto={_id}{...listProps}/>,type: 'component'}// or create a custom action (e.g. popup, do not use this for routing – UX)constedit={action: doc=>this.props.history.push(`${this.props.match.url}/edit/${doc._id}`)}// remove action (default)// or use the same structure as editconstremove=doc=>Meteor.call('removeDoc',doc._id)constextraColumns=[{name: 'fullname',// used to match compactvalue: ({ firstname, lastname })=>firstname+' '+lastname,label: 'Full Name',// title of custom columnfields: ['firstname','lastname'],// list of fields needed for this columnplaceholder: 'must be or return a string'},{name: 'score',value: doc=>Math.round(doc.percentage*100),label: 'Score',fields: ['percentage'],search: {// search definition for custom columnsfields: 'percentage',// field(s) on which to search (string or array)value: value=>value/100// basically the reverse logic of value (value or array)},// OR search can be a function for async stuff:search: ({ value, changeQuery })=>{Meteor.call('percentageSearch',value,(e,r)=>{changeQuery('percentage',r)// call should return an array})},placeholder: ()=>'must be or return a string'},]// set prefix for displaying of images// ! no trailing forward slash: '/'constprefix={imageField: 'https://s3-eu-west-1.amazonaws.com/your-bucket'}conststateHasChanged=({ page, total, sort, ...childState})=>this.setState({showList: !!total})<Listcollection={Collection}getIdsCall='getIds'// or: getIdsCall={{call:'methodName',arguments:'methodArguments'}}subscription='subscription'fields={fields}fieldsCompact={fieldsCompact}getTotalCall='totalDocs'// or: getTotalCall={{call:'methodName',arguments:'methodArguments'}}defaultQuery={{type: 'only_show_this_type'}}defaultSort={{name: 1}}remove={remove}edit={edit}extraColumns={extraColumns}onStateChange={stateHasChanged}urlPrefix={prefix}/>// inject your logic before returning (security, filtering deleted, …)// this function is reusable for required methodsconstgetItems=(query={},params={})=>Collection.find(query,params)Meteor.publish("subscription",getItems)Provide a Meteor method to get the ids for the current query.
Meteor.methods({getIds: (query,params)=>getItems(query,params).map(({ _id })=>_id)})Provide a Meteor method to get a total document count.
Meteor.methods({getTotals: (query)=>getItems(query,{fields: {_id: 1}).count()})This function is called only
- when the state of the list has changed (query, sorting, …)
- when the total amount of visible items is known (getTotalCall has got a result)
This function receives the latest state of the list ({ page, total, sort, query, ids, ...childState }).
Example usage:
- use the property total to show/hide the list and adjacent components (set state of parent component)
- show the total amount outside the list
<h1>Users ({total})</h1>
Import a file with this structure on startup:
import{library}from'@fortawesome/fontawesome-svg-core'import{ ...icons}from'@fortawesome/free-solid-svg-icons'library.add(...icons)The pagination component is exposed too:
import{Pagination}from'meteor/lef:adminlist'constPages=props=><Pagination{...props}/>Pagination.propTypes={page: PropTypes.number.isRequired,// current page number, zero-basedpages: PropTypes.number.isRequired,// amount of pagessetPage: PropTypes.func.isRequired// method to set page}