Martin Nordström
Martin Nordström

Reputation: 6025

Display lists of list items based on similar dates

Currently I have this list:

enter image description here As you can see these items have the same date, 21/09. And when a list item has the same date (yyyy/mm/dd) I want it to look like this:

(sorry for my drawing)

enter image description here

I want to group items that has the same date under a header that tells their common date.

I've been trying to tackle this idea for a while now, but I can't get started. Every time I come up with something it doesn't work (sad I know).

I think I first need to get all events items date in the format yyyy/mm/dd and then somehow check if evens on that date contains one or more events. And if they do, they'll get a header with their date and all of the events will be displayed below. Otherwise nothing will be shown.

If you have any tips please let me know!!

Thanks for reading.

Edit

So the parent component that hold all these list is dash.js:

events
  .slice(-this.state.showCount)
  .reverse()
  .map((event, i) => {
    var driver = event.driver ? keyedDrivers[event.driver] : false
    var carrier = driver ? keyedCarriers[driver.carrier] : false
    var customer = event.customer
      ? keyedCustomers[event.customer]
      : false

    return (
      <div key={i}>
        <EventItem // This is the list item
          event={event}
          customer={customer}
          carrier={carrier}
          driver={driver}
          lock={keyedLocks[event.unit] || { address: {} }}
        />
      </div>
    )
  })

And inside of EventItem I simply use all of the props I passed to EventItem to display a list.

Also, it's the event object that contains the date:

A event object:

_id: ObjectId("12345")
customer: ObjectId("54321")
timestamp: 2017-08-25T12:04:14.001Z

Upvotes: 1

Views: 351

Answers (2)

bennygenel
bennygenel

Reputation: 24660

Lodash has a method called groupBy. I think you can make use of it. There are also methods you can use without a third party library.

Example

let eventsGroups = _.groupBy(events, (event) => moment(event.timestamp).format('YYYY/MM/DD'))

renderEvents() {
  return Object.keys(eventsGroups).map((groupName) => {
    return (
      <div>
        { renderHeader(groupName) }
        { renderEvents(eventsGroups[groupName]) }
      </div>
    )
  });
}

renderHeader(groupName) {
  return <h1>{groupName}</h1>
}

renderEvents(events) {
  return events.map((event) => {
    return <EventItem event={event} />
  })
}

Upvotes: 1

Ross Mackay
Ross Mackay

Reputation: 972

The best way to do this is probably to convert your one input list into a list of groups (by date)

const input = [{date: '21/09'}, {date: '21/09'},
               {date: '22/09'}, {date: '23/09'},
               {date: '24/09'}, {date: '24/09'}]

Now you can reduce this from a list, into an objet keyed by dates

const output = input.reduce((dates, item) => {
    if (dates[item.date]) {
        dates[item.date].push(item)
    } else {
        dates[item.date] = [item]
    }

    return dates
}, {})

// returns

{
  '21/09': [
    { date: '21/09' },
    { date: '21/09' },
  ],
  '22/09': [{ date: '22/09' }],
  '23/09': [{ date: '23/09' }],
  '24/09': [
    { date: '24/09' },
    { date: '24/09' },
  ]
}

You can then do

Object.keys(output).map(date => (
  <div key={date}>
    <Heading>{date}</Heading>
    {output[date].map(item => (
      <Item>
      ...
      </Item>
    ))}
  </div>
))

There's plenty you can to do tidy up that code, but hopefully it's enough to get started

Upvotes: 1

Related Questions