Listview for calendar component

var newData = [];
let items = {{formatDataAsArray(query7.data)}}
items.forEach((event,i) => {
    newData.push({
   // start: event.start,
      start: event.startTime,
      end: event.endTime,
      title: event.summary,
      id: i+1
  })
});
return newData```

Here's the working code (works for me, but let me know if it doesn't work for you)!

let newData = [];
const items = {{formatDataAsArray(getUsersFromMultiselect.data)}};
items.forEach((event,i) => {
 newData.push({
 start: event.created_at,
 end: event.updated_at,
 title: event.project_type,
 id: i+1,
 facilitator: event.Facilitator
 })
});

const arrayOfObjects = newData;

const result = arrayOfObjects.reduce((acc, obj) => {
  const found = acc.find(a => a[0].facilitator == obj.facilitator);
  if (found) {
    found.push(obj);
  } else {
    acc.push([obj]);
  }
  return acc;
}, []);

return result;

For context, @fish_hatchery came to Retool Office Hours and we were working on setting up a dynamic number of calendars depending on how many users were selected in a multiselect (1 calendar per user).

We need to modify the JS transformer (pasted above) that currently only works for a SQL query that returns 1 user's calendar events.

Our SQL query now returns all events that have an owner that matches a user selected from a multiselect and we need to organize the data so it returns an array of arrays of objects, where each subarray represents a user and each object represents a single event.

To sort an array of objects (which is what we're currently starting with from our SQL query formatted as an array of objects) into an array of arrays (of objects), you can use the Array.prototype.reduce() method. This method let us iterate over an array and apply a reducer function to each element. The reducer function takes the accumulator (in this case, the result array) and the current element as arguments, and returns the updated accumulator.

Here's a general example of how you can use Array.prototype.reduce() to sort an array of objects into an array of arrays:

const arrayOfObjects = [ { name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }, { name: 'Charlie', age: 35 }, { name: 'Alice', age: 40 } ]; 

const result = arrayOfObjects.reduce((acc, obj) => { 
const found = acc.find(a => a[0].name === obj.name); 

      if (found) { found.push(obj); } 
      else { acc.push([obj]); } 
return acc; }, []); 

return result;

This will output the following:

[ [{ name: 'Alice', age: 25 }, { name: 'Alice', age: 40 }], [{ name: 'Bob', age: 30 }], [{ name: 'Charlie', age: 35 }] ]

Note that this solution assumes that the objects in the array have a name property. If the objects have a different property that you want to use for sorting, you can simply replace obj.name with the appropriate property in the acc.find() and found.push() calls.

Thank you for putting this together, Victoria!

It works great - the only issue I'm having now is parsing the facilitator name from each bundle. I've set a text box to

{{query7.data.Facilitator[i]}}

but it gives me the same person over and over even though the events are different (which is the part that works!) Perhaps I need to reference a different query?

Ooh, never mind - I figured it out! I had 1 button too many. I simply set the textbox in the listview as

'{{multiselect1.value[i]}} '

and it pulled in the correct folks for each calendar. Thanks again!

Awesome!!! You should also be able to do something like:

{{ newTransformer.value[i].facilitator }}

Interestingly pointing to the transformer didn't work. I'm not sure why but it passes a null value. Not a big deal though, using the multiselect was ok! Thanks again for all your hard work on getting this working for me. Appreciate it!

Oh weird. Well, glad to hear you’re up and running! Let me know if you ever want to debug why the transformer isn’t working and write back in anytime :slightly_smiling_face:

Thanks for coming to office hours! See ya around soon.