MUI datatable sorting column - javascript

I have a column that is basically an object, I display the value I want to display, but the sort does not work for that column.
Attach an example so I can explain myself a little better.
for example:
const [data, setData] = useState([
{
ID: "A001",
Name: "Joe James",
Amount: "$300,000",
Purpose: "$220,000",
Tib: 12 + "years",
details: {Score: "620-670" , Name:"Joe James"},
Score: "620-670",
Phone: "9292132019",
Mail: "Nole#temp.io",
State: "TX",
Opening: "11.11.2021",
Pf: "Priority urgent",
Flags: "In Progress",
Ls: "DorAff",
Company: "Dit",
Ras: "...",
},
{
ID: "A001",
Name: "Joe James",
Amount: "$300,000",
Purpose: "$220,000",
Tib: 12 + "years",
details: {Score: "650-720" , Name:"Test James"},
Score: "620-670",
Phone: "9292132019",
Mail: "Noe#temp2t.io",
State: "TX",
Opening: "11.11.2021",
Pf: "Priority urgent",
Flags: "In Progress",
Ls: "DavAff",
Company: "Mit",
Ras: "...",
}
)];
const columns = [
{
name: "details",
label: "Name",
options: {
customBodyRender: (value: any, tableMeta: any, updateValue: any) => {
return value?.Name;
},
sort: true,
filter: true,
setCellProps: () => ({
align: "center",
}),
setCellHeaderProps: (value: any) => ({
className: "centeredHeaderCell",
}),
},
},
{
name: "details",
label: "Score",
options: {
filter: true,
sort: true,
customBodyRender: (value: any, tableMeta: any, updateValue: any) => {
return value?.Score;
},
setCellProps: () => ({
align: "center",
}),
setCellHeaderProps: (value: any) => ({
className: "centeredHeaderCell",
}),
},
}
]
As you can see in the example I go to the details and display the Name, and in another column displays the Score.
Thanks in advance :-)

You can use it in a simple way. You just have to put the name of the column and the direction. Inside the table options
sortOrder: {
name: 'name',
direction: 'desc'
}
So your code would be something like this
const [data, setData] = useState([
{
ID: "A001",
Name: "Joe James",
Amount: "$300,000",
Purpose: "$220,000",
Tib: 12 + "years",
details: {Score: "620-670" , Name:"Joe James"},
Score: "620-670",
Phone: "9292132019",
Mail: "Nole#temp.io",
State: "TX",
Opening: "11.11.2021",
Pf: "Priority urgent",
Flags: "In Progress",
Ls: "DorAff",
Company: "Dit",
Ras: "...",
},
{
ID: "A001",
Name: "Joe James",
Amount: "$300,000",
Purpose: "$220,000",
Tib: 12 + "years",
details: {Score: "650-720" , Name:"Test James"},
Score: "620-670",
Phone: "9292132019",
Mail: "Noe#temp2t.io",
State: "TX",
Opening: "11.11.2021",
Pf: "Priority urgent",
Flags: "In Progress",
Ls: "DavAff",
Company: "Mit",
Ras: "...",
}
)];
const columns = [
{
name: "name",
label: "Name",
options: {
sort: true,
filter: true,
setCellProps: () => ({
align: "center",
}),
setCellHeaderProps: (value: any) => ({
className: "centeredHeaderCell",
}),
},
},
{
name: "score",
label: "Score",
options: {
filter: true,
sort: true,
setCellProps: () => ({
align: "center",
}),
setCellHeaderProps: (value: any) => ({
className: "centeredHeaderCell",
}),
},
}
];
const options = {
sortOrder: {
name: 'name',
direction: 'desc'
},
};

I was able to solve this, using the sortCompare function from the documentation!
https://www.npmjs.com/package/mui-datatables/v/3.3.1

You can add sortOrder in MUI Data Table Options
sortOrder: {
name: 'name',
direction: 'desc'
}
Example: https://github.com/gregnb/mui-datatables/blob/master/examples/customize-columns/index.js
sortOrder: Sets the column to sort by and its sort direction. To remove/reset sorting, input in an empty object. The object options are the column name and the direction: name: string, direction: enum('asc', 'desc')

Related

Comparing two arrays - removing element from array based on object keys

I have two objects.
const arrayOne = [
{
label: "Categories",
to: "/categories",
id: "product_type",
},
{
label: "Colors",
to: "/colors",
id: "color",
},
{
label: "Materials",
to: "/materials",
id: "material",
},
{
label: "Sizes",
to: "/sizes",
id: "sizes",
},
{
label: "Designers",
to: "/designers",
id: "designer_slug",
},
{
label: "Stores",
to: "/stores",
id: "retailer_slug",
},
];
const arrayTwo = [
{
id: "gender",
label: "Gender",
lazy_loaded: false,
},
{
id: "product_type",
label: "Category",
lazy_loaded: false,
},
{
id: "quick_filters",
label: "Quick filters",
lazy_loaded: false,
},
{
id: "final_price",
label: "Price",
lazy_loaded: false,
},
{
id: "color",
label: "Color",
lazy_loaded: false,
},
{
id: "material",
label: "Material",
lazy_loaded: false,
},
{
id: "designer_slug",
label: "Brand",
lazy_loaded: true,
},
{
id: "retailer_slug",
label: "Store",
lazy_loaded: true,
},
];
As you can see they both have the key 'id'. If the IDs in arrayOne aren't in arrayTwo, I would like them to be removed from arrayOne (the whole object). So in this case, only the object with "sizes" should be removed from arrayOne. How would I go about doing this? Thanks in advance!
you could utilize filter:
const newArrayOne = arrayOne.filter(x => arrayTwo.find(y => y.id === x.id))
You could use a Set with id and filter the other array.
const
arrayOne = [{ label: "Categories", to: "/categories", id: "product_type" }, { label: "Colors", to: "/colors", id: "color" }, { label: "Materials", to: "/materials", id: "material" }, { label: "Sizes", to: "/sizes", id: "sizes" }, { label: "Designers", to: "/designers", id: "designer_slug" }, { label: "Stores", to: "/stores", id: "retailer_slug" }],
arrayTwo = [{ id: "gender", label: "Gender", lazy_loaded: false }, { id: "product_type", label: "Category", lazy_loaded: false }, { id: "quick_filters", label: "Quick filters", lazy_loaded: false }, { id: "final_price", label: "Price", lazy_loaded: false }, { id: "color", label: "Color", lazy_loaded: false }, { id: "material", label: "Material", lazy_loaded: false }, { id: "designer_slug", label: "Brand", lazy_loaded: true }, { id: "retailer_slug", label: "Store", lazy_loaded: true }],
two = new Set(arrayTwo.map(({ id }) => id)),
result = arrayOne.filter(({ id }) => two.has(id));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How can I put the data inside the table?

I am using mui-datatables. I can already retrieve the data correctly. However, I am quite lost on how to display the data address, ID, and name, and date only in the table.
codesandbox link :https://codesandbox.io/s/infallible-feistel-bki5h?file=/src/App.js
This is the data in a JSON format.
[
{
name: "Sample Name",
items: {
id: "34234242",
selectedItem: "Item",
date: { seconds: 1636905600, nanoseconds: 0 },
item1: true,
item2: false,
},
address: "Ayala",
email: "sample email",
phone: "823840820943",
},
];
Below are the codes.
const filter = users.filter((d) => d?.items?.item2 == false);
const filtered = selection.filter((f) => f?.items?.date <= new Date());
return (
<div>
{" "}
<MUIDataTable title={"List"} columns={columns} data={filtered} />
</div>
);
};
export default UserTable;
You need columns options where you include address, ID, name, and date. You can also hide column (using display: false) that are included into your column list. please the below example and you can check MUI Datatable documentation too.
import MUIDataTable from "mui-datatables";
const columns = [
{
name: "name",
label: "Name",
options: {
filter: true,
sort: true,
}
},
{
name: "company",
label: "Company",
options: {
filter: true,
sort: false,
}
},
{
name: "city",
label: "City",
options: {
filter: true,
sort: false,
display: false,
}
},
{
name: "state",
label: "State",
options: {
filter: true,
sort: false,
}
},
];
const data = [
{ name: "Joe James", company: "Test Corp", city: "Yonkers", state: "NY" },
{ name: "John Walsh", company: "Test Corp", city: "Hartford", state: "CT" },
{ name: "Bob Herm", company: "Test Corp", city: "Tampa", state: "FL" },
{ name: "James Houston", company: "Test Corp", city: "Dallas", state: "TX" },
];
const options = {
filterType: 'checkbox',
};
<MUIDataTable
title={"Employee List"}
data={data}
columns={columns}
options={options}
/>
Update based on your comment
You need to consider two things:
Need to use customBodyRender to show complex json data like items.SelectedItem
{
name: "items",
label: "Item",
options: {
filter: true,
sort: true,
customBodyRender: (value, tableMeta, updateValue) => {
console.log(value, tableMeta, updateValue, "test");
return value.selectedItem;
}
}
}
Need to use setRowProps to show background color of selected row based on condition. you need options to use setRowProps
const options = {
filter: true,
filterType: "dropdown",
fixedSelectColumn: false,
rowHover: false,
setRowProps: (row, dataIndex, rowIndex) => {
return {
style: row[1] === "Item" ? { backgroundColor: "skyblue" } : {}
};
}
};
Here is the complete example:
Updated Example in Codesandbox

JS: Group an array of object by specific field into section list

I have such data:
const data = [
{
id: '1',
name: 'River',
address: 'Terminal A',
type: 'OTHER',
code: null,
targetArrivalStep: 30,
disabled: true,
},
{
id: '2',
name: 'Afer',
address: 'Afer train station',
type: 'TRAIN_STATION',
code: 'MTS',
targetArrivalStep: 0,
disabled: false,
},
{
id: '3',
name: 'Fidel',
address: 'HHH',
type: 'OTHER',
code: '',
targetArrivalStep: 0,
disabled: false,
},
{
id: '5',
name: 'Train station',
address: 'Patrick str.',
type: 'TRAIN_STATION',
code: null,
targetArrivalStep: 0,
disabled: false,
},
{
id: '7',
name: 'qqq',
address: 'qqq',
type: 'BUS_STATION',
code: null,
targetArrivalStep: 60,
disabled: false,
},
];
I need to group it by type.
Here's the desired output:
const res = [
{
type: 'OTHER',
data: [
{
id: '1',
name: 'River',
address: 'Terminal A',
type: 'OTHER',
code: null,
targetArrivalStep: 30,
disabled: true,
},
{
id: '3',
name: 'Fidel',
address: 'HHH',
type: 'OTHER',
code: '',
targetArrivalStep: 0,
disabled: false,
},
],
},
{
type: 'TRAIN_STATION',
data: [
{
id: '2',
name: 'Afer',
address: 'Afer train station',
type: 'TRAIN_STATION',
code: 'MTS',
targetArrivalStep: 0,
disabled: false,
},
{
id: '5',
name: 'Train station',
address: 'Patrick str.',
type: 'TRAIN_STATION',
code: null,
targetArrivalStep: 0,
disabled: false,
},
],
},
{
type: 'BUS_STATION',
data: [
{
id: '7',
name: 'qqq',
address: 'qqq',
type: 'BUS_STATION',
code: null,
targetArrivalStep: 60,
disabled: false,
},
],
},
];
Here's my solution:
const result = data.reduce((c, item) => {
c[item.type] = c[item.type] || [];
c[item.type].push(item);
return c;
}, {});
I don't like the mutation of reduce arguments. Is there any other way to solve this task?
As stated in the comments, mutating the accumulator is perfectly reasonable: it is freshly created for this specific function call and only gets altered internally and without interruption. Seen from the outside, your solution is a pure function with no side effects.
For the sake of the example though, this is how you could rewrite your solution in a declarative fashion using some fancy destructuring magic:
const result = data.reduce((c, item) => ({...c, [item.type]:[...c[item.type] ?? [], item]}), {});
Explanation:
const result = data.reduce(
(c, item) => ({ // Return a new object
...c, // Copy the previous object into it
[item.type]: [ // Overwrite the current type group
...(c[item.type] ?? []), // Copy the old items of that group (or an empty array)
item // Add the current item
] }),
{}
);
It's pretty clear to me however that your original solution is the more readable and thus superior one.

How to nest multiple groupby with loadash/javascript

Thank you in advance to whoever can help me. I am trying to display data using SectionList in React Native. I have written my code below displaying what I am trying to accomplish. A regular javascript solution will work. I want the data to first be grouped together by date, and inside of that date, I need them grouped by location.
It's important that it has a title and data key
I have data in this format:
[ { game_id: 1171,
date: '2018-11-17',
location: 'Plaza'
},
{ game_id: 1189,
date: '2018-11-17',
location: 'Field - Kickball'
},
{ game_id: 1489,
date: '2018-11-16',
location: 'Field - Kickball'
},
{ game_id: 1488,
date: '2018-11-16',
location: 'Field - Soccer'
}
]
I need the output to show:
data = [{
title: "2018-11-17",
data: [{
title: "Field - Kickball",
data: [{
game_id: 1189,
date: '2018-11-17',
location: 'Field - Kickball'
}]
},
{
title: "Plaza",
data: [{
game_id: 1171,
date: '2018-11-17',
location: 'Plaza'
}]
}
]
},
{
title: "2018-11-16",
data: [{
title: "Field - Kickball",
data: [{
game_id: 1489,
date: '2018-11-16',
location: 'Field - Kickball'
}]
},
{
title: "Field - Soccer",
data: [{
game_id: 1488,
date: '2018-11-16',
location: 'Field - Soccer'
}]
}
]
}
]
I have already tried this
const games = [data here]
var groups = _(games)
.groupBy(x => x.date)
.map(value => {
return _.groupBy(value, 'location')
.map(({key, value}) => ({title: key, data: value}))
})
.map((value, key) => {
return ({title: value[Object.keys(value)[0]][0].date, data: value})
})
Use reduce like so:
const data = [{game_id:1171,date:'2016-11-17T05:00:00.000Z',time:'08:00:00',category:'Ch B Coed',background:'#FFFF00',textcolor:'#000000',bold:0,sport:'Newcomb',location:'Plaza',text:'COL2 vs. USA1 1171'},{game_id:1189,date:'2016-11-17T05:00:00.000Z',time:'08:50:00',category:'Ch A Coed',background:'#FF33CC',textcolor:'#000000',bold:0,sport:'Kickball',location:'Field - Kickball',text:'COL1 vs. USA1 1189'},{game_id:1489,date:'2016-2-17T05:00:00.000Z',time:'04:50:00',category:'Ch B Coed',background:'#FF33CC',textcolor:'#000000',bold:0,sport:'Kickball',location:'Field - Kickball',text:'COL2 vs. USA3 1489'}];
const res = Object.values(data.reduce((acc, { date, ...rest }) => acc[date] ? { ...acc, [date]: { ...acc[date], data: acc[date].data.concat({ date, ...rest })} } : { ...acc, [date]: { title: date, data: [{ date, ...rest }] }}, {}));
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: auto; }
Pardon me if I am missing something but this to me it seems can be done in somewhat simpler manner via Array.reduce:
let data = [{ game_id: 1171, date: '2016-11-17T05:00:00.000Z', time: '08:00:00', category: 'Ch B Coed', background: '#FFFF00', textcolor: '#000000', bold: 0, sport: 'Newcomb', location: 'Plaza', text: 'COL2 vs. USA1 1171' }, { game_id: 1189, date: '2016-11-17T05:00:00.000Z', time: '08:50:00', category: 'Ch A Coed', background: '#FF33CC', textcolor: '#000000', bold: 0, sport: 'Kickball', location: 'Field - Kickball', text: 'COL1 vs. USA1 1189' }, { game_id: 1489, date: '2016-2-17T05:00:00.000Z', time: '04:50:00', category: 'Ch B Coed', background: '#FF33CC', textcolor: '#000000', bold: 0, sport: 'Kickball', location: 'Field - Kickball', text: 'COL2 vs. USA3 1489' } ]
let result = data.reduce((r, c) => {
r[c.date] = r[c.date] || {title: c.date, data: []}
r[c.date].data = [...(r[c.date].data || []), c]
return r
}, {})
console.log(Object.values(result))

Mongoose query document with multiple fileds including sub field Mongodb

Hi I have following model of a document in mongodb
Schema is
const ProductionsSchema=new Schema({
name: {type: String, required: true, unique: true},
isActive: {type: Boolean, default: true},
locations: [{
name: {type: String},
isActive : {type: Boolean, default: false}
}],
trackno: {type: String}
})
Productions:[{
_id: 125,
name: 'John Smith',
locations: [{ name: 'Boston', isActive: true}]
isActive: true,
trackno: 2123
},
{
_id: 126,
name: 'Moe Adam',
locations: [{ name: 'Chicago', isActive: true}]
isActive: true,
trackno: 5663
},
{
_id: 126,
name: 'Henry Noel',
locations: [{ name: 'Houston', isActive: false}]
isActive: true,
trackno: 4552
},
{
_id: 128,
name: 'Tim Johnson',
locations: [{ name: 'Denver', isActive: true}]
isActive: false,
trackno: 6672
}
]
I am trying to find list of with both isActive true
Productions.find({"isActive" : true , "locations.isActive": true}, (err, list)=>{
if(err){
callback(err);
}
callback(null, list)
})
I am trying to write query so both isActive are true. In above sample data only first two records should be in the answer. But I keep getting all the records even ones with 'false' I even tried $elemMatch on locations.isActive still didnt work.
Please let me know how I can fix this so that I only get result that contains only true values for both isActive.
As the original comment explained, the only query conditions you need are:
{ isActive: true, "locations.isActive": true }
This is a basic AND condition, and you don't need any special operators just to verify a condition is met on a single property anywhere in an array, which is all you are asking.
Since this works exactly as expected, I can only think to show you a full working listing to use as a basis to work out what you are doing differently thus causing you to not get the same result as what is expected.
const { Schema } = mongoose = require('mongoose');
const uri = 'mongodb://localhost:27017/productions';
const opts = { useNewUrlParser: true };
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);
mongoose.set('debug', true);
const productionSchema = new Schema({
name: String,
isActive: { type: Boolean, default: true },
locations: [{
name: String,
isActive: { type: Boolean, default: false }
}],
trackno: Number
})
const Production = mongoose.model('Production', productionSchema);
const data =
[
{
name: 'John Smith',
locations: [{ name: 'Boston', isActive: true}],
isActive: true,
trackno: 2123
},
{
name: 'Moe Adam',
locations: [{ name: 'Chicago', isActive: true}],
isActive: true,
trackno: 5663
},
{
name: 'Henry Noel',
locations: [{ name: 'Houston', isActive: false}],
isActive: true,
trackno: 4552
},
{
name: 'Tim Johnson',
locations: [{ name: 'Denver', isActive: true}],
isActive: false,
trackno: 6672
}
];
const log = data => console.log(JSON.stringify(data, undefined, 2));
(async function() {
try {
const conn = await mongoose.connect(uri, opts);
// clean data
await Promise.all(
Object.entries(conn.models).map(([k, m]) => m.deleteMany())
);
// set up
await Production.insertMany(data);
// Query
let query = { isActive: true, "locations.isActive": true };
let results = await Production.find(query);
log(results);
} catch(e) {
console.error(e)
} finally {
mongoose.disconnect()
}
})()
Which outputs the two expected documents:
Mongoose: productions.deleteMany({}, {})
Mongoose: productions.insertMany([ { isActive: true, _id: 5c7f7e9367daed19d6773e9b, name: 'John Smith', locations: [ { isActive: true, _id: 5c7f7e9367daed19d6773e9c, name: 'Boston' } ], trackno: 2123, __v: 0 }, { isActive: true, _id: 5c7f7e9367daed19d6773e9d, name: 'Moe Adam', locations: [ { isActive: true, _id: 5c7f7e9367daed19d6773e9e, name: 'Chicago' } ], trackno: 5663, __v: 0 }, { isActive: true, _id: 5c7f7e9367daed19d6773e9f, name: 'Henry Noel', locations: [ { isActive: false, _id: 5c7f7e9367daed19d6773ea0, name: 'Houston' } ], trackno: 4552, __v: 0 }, { isActive: false, _id: 5c7f7e9367daed19d6773ea1, name: 'Tim Johnson', locations: [ { isActive: true, _id: 5c7f7e9367daed19d6773ea2, name: 'Denver' } ], trackno: 6672, __v: 0 } ], {})
Mongoose: productions.find({ isActive: true, 'locations.isActive': true }, { projection: {} })
[
{
"isActive": true,
"_id": "5c7f7e9367daed19d6773e9b",
"name": "John Smith",
"locations": [
{
"isActive": true,
"_id": "5c7f7e9367daed19d6773e9c",
"name": "Boston"
}
],
"trackno": 2123,
"__v": 0
},
{
"isActive": true,
"_id": "5c7f7e9367daed19d6773e9d",
"name": "Moe Adam",
"locations": [
{
"isActive": true,
"_id": "5c7f7e9367daed19d6773e9e",
"name": "Chicago"
}
],
"trackno": 5663,
"__v": 0
}
]

Categories