i have an API Laravel response such this:
{
id:1,
name: "Text",
category: {
id: 1,
name: "Text 2",
},
tags:[
{
id: 1,
name: "Tag1",
},
{
id: 2,
name: "Tag2",
},
],
},
For my front-end (with vuejs) i've created a simple computed function to filter the category, based on the user's selection of checkboxes.
checkedCategory: []
.
.
let posts = this.posts;
if (typeof this.checkedCategory !== 'undefined' && this.checkedCategory.length > 0) {
posts = posts.filter((post) => {
return this.checkedCategory.indexOf(post.category.name) > -1;})}
Everything works.Posts are filtered by the categories chosen by the user.
But, posts can also have several tags.
Is an array of objects, so i reformulated the block with an .includes (instead of .filter), but it returns an empty result.
checkedTags: []
.
.
let posts = this.posts;
if (typeof this.checkedTags !== 'undefined' && this.checkedTags.length > 0) {
posts = posts.includes((post) => {
return this.checkedTag.indexOf(post['tags']) > -1;})}
I think this should work:
let posts = this.posts;
if (typeof this.checkedTags !== 'undefined' && this.checkedTags.length > 0) {
posts = posts.filter(post => {
return post.tags.some(tag => checkedTags.includes(tag.name))
})
}
Basically it will just filter all the posts where at least one tag is in the checkedTags array. Depending on your needs you can also check if all the tags of the post are there with post.tags.every()
Related
I want check whether document front and back object is present in an array. If both
front and back object is present set document to true or if only front is present set document to false
const [document, setDocument] = useState('');
let data = [
{ id: 1, type:'document', frontBack:'front'},
{ id: 2, type:'pan', frontBack:'front'},
{ id: 3, type:'profile', frontBack:'front'},
{ id: 4, type:'document', frontBack:'back'},
];
You can check if data has a frontBack:'front' with this code:
data.find(({type, frontBack})=> type == 'document' && frontBack == 'front')
And you can check if data has a frontBack:'back' with this code:
data.find(({type, frontBack})=> type == 'document' && frontBack == 'back')
If both expressions return an object, you have both.
If any of them return undefined, you don't.
There are multiple approaches to solving this problem, but you could make use of .some() method to check if the criteria mentioned above are satisfied or not.
setDocument(data.some(item=>item.frontBack === 'front') && data.some(item=>item.frontBack === 'back'))
.some() returns true if one or more items in the iterable returns true, so we are checking if both front and back exists, and using the conditional && we can say if both the items exist or not and set the state accordingly. You can also make the code more understandable by extracting the logical operation result into a separate variable, like so:
const res = data.some(item=>item.frontBack === 'front') && data.some(item=>item.frontBack === 'back')
setDocument(res)
I tried to write it out in as straightforward a way as possible. I wasn't sure which variable you meant to set, so I used one called setDoc:
//const [document, setDocument] = useState('');
let data = [
{ id: 1, type:'document', frontBack:'front'},
{ id: 2, type:'pan', frontBack:'front'},
{ id: 3, type:'profile', frontBack:'front'},
{ id: 4, type:'document', frontBack:'back'},
];
let setDoc, front, back = false
data.forEach(obj => {
if(obj.type === 'document' && obj.frontBack === 'front') {
front = true
}
if(obj.type === 'document' && obj.frontBack === 'back') {
back = true
}
})
setDoc = front && back
console.log(setDoc)
You can use some method of Array object, which returns true if some of the elements pass the given test.
let data = [{
id: 1,
type: 'document',
frontBack: 'front'
},
{
id: 2,
type: 'pan',
frontBack: 'front'
},
{
id: 3,
type: 'profile',
frontBack: 'front'
},
{
id: 4,
type: 'document',
frontBack: 'back'
},
];
let out = data.some(d => d.type == "document" && d.frontBack == "front") && data.some(d => d.type == "document" && d.frontBack == "back");
console.log(out);
I have an array of objects like this:
"result": [
{
"UserGroupName": "TestCronGroup2",
"CourseTitle": "Test Publish Course 1",
"ComplianceStatus": false
},
{
"UserGroupName": "TestCronGroup2",
"CourseTitle": "test456",
"ComplianceStatus": null
},
{
"UserGroupName": "TestCronGroup2",
"CourseTitle": "retest456",
"ComplianceStatus": null
},
{
"UserGroupName": "TestCronGroup1",
"CourseTitle": "Test Publish Course 1",
"ComplianceStatus": false
},
And I want it to convert it in a matrix form like this:
Compliance Report Matrix
This is my code so far. I am unable to link the values in matrix properly:
showItems = (columns: any) => {
var columnsArr = new Array();
columnsArr = [
{
title: "Course",
field: "CourseTitle",
},
];
Object.keys(this.props.complianceReport).forEach((key, index) => {
var columnsObj = {
title: this.props.complianceReport[key].UserGroupName,
};
columnsArr.push(columnsObj);
});
return (
<div>
<ReportsTable
columns={columnsArr}
tableData={this.props.complianceReport}
/>
</div>
);
};
What I am able to achieve so far:
My Matrix so far
I am new to react and javascript so any kind of help will be appreciated. Thanks!
There are few things you should start to prepare data for react-table output. First thing is to create array of all the columns (course and unique usergroups) and second array of the unique courses.
// prep columns (usergroups unique)
// use Set to aviod duplicates
let userGroups = new Set();
result.forEach(item => userGroups.add(item.UserGroupName));
let columns = Array.from(userGroups)
.sort()
.map(item => {
return {
Header: item,
accessor: item
};
});
// add column: Courses in front
columns.unshift({ Header: "Courses", accessor: "courses" });
// prep courses (unique)
let courseTitles = new Set();
result.forEach(item => courseTitles.add(item.CourseTitle));
const courseTitlesItems = Array.from(courseTitles).sort();
When you have both of these you can iterate through all the courses and check if it is available for specific usergroup.
// prep data
let data = courseTitlesItems.map(courseItem => {
return {
...columns.reduce(
(o, column) =>
Object.assign(o, {
[column.accessor]: testCourse(result, courseItem, column)
}),
{}
),
courses: courseItem
};
});
Use this function to test for data.
function testCourse(result, courseItem, column) {
const foundItem = result.find(
resultItem =>
resultItem.CourseTitle === courseItem &&
resultItem.UserGroupName === column.accessor
);
return foundItem === undefined || foundItem.ComplianceStatus === null
? "-"
: foundItem.ComplianceStatus === false
? "No"
: "Yes";
}
Demo and the playground I used to solve your quiz. Hope you will find it useful!
https://codesandbox.io/s/react-table-vr0ky?file=/src/App.js
I'm having two data arrays which are coming from API and sample arrays would be like this
Array 1
[
{userId: 1
description: "Student"
imagePath: "test.png"
status: 1
}]
Array 2
[
{id: 85
accountName: "Rahul"
accountNumber: "11145678"
}
]
In my reactnative app view there's search bar and user should be able to search from these two arrays. So I merged these two arrays into one using
this.searchArray =this.filterArray[0].concat(this.filterArray[1])
So, my searchArray is a single array with Array1 and Array2 data. sample below
[
{userId: 1
description: "Student"
imagePath: "test.png"
status: 1
},
{id: 85
accountName: "Rahul"
accountNumber: "11145678"
}]
My search function is below (I need to search from account number or description)
//Search Filter
searchFilter =searchText=>{
const searchTextData = searchText.toUpperCase();
const userSearch = this.searchArray.filter(item => {
const itemData = `${item.description && item.description.toUpperCase()} ${item. accountName && item.accountName.toUpperCase()}`;
return itemData.indexOf(searchTextData) > -1;
});
}
The search functionality is not working with accountName. It's not getting any results. But if I remove ${item. accountName && item.accountName.toUpperCase()} , then it's working showing data with description. But I need to filter from both
In your array one object can have description or accountNumber so do a check if that exists include it in the itemData variable.
Try doing this
searchFilter =searchText=>{
const searchTextData = searchText.toUpperCase();
const userSearch = this.searchArray.filter(item => {
const itemData = `${item.hasOwnProperty('description'))?item.description.toUpperCase():''} ${item.hasOwnProperty('accountNumber')?item.accountNumber:''}`;
return itemData.indexOf(searchTextData) > -1;
});
}
First merge the two objects into one:
Object.keys(arr2[0]).forEach(key => {
arr1[0][key] = arr2[0][key]
})
Then create the search function:
function searchObject(obj, value){
return Object.keys(obj).some(key => {
return obj[key] === value
})
}
let arr1=[{userId:1,description:"Student",imagePath:"test.png",status:1}],arr2=[{id:85,accountName:"Rahul",accountNumber:"11145678"}];
Object.keys(arr2[0]).forEach(key => {
arr1[0][key] = arr2[0][key]
})
function searchObject(obj, prop, value){
return obj[prop] === value
}
console.log(searchObject(arr1[0], "accountName", "asdf"))
console.log(searchObject(arr1[0], "accountName", "Rahul"))
I am trying to find each link value in different variables according to their name , like if name if facebook then facebooklink should filter , same lite twitter and all . But don't want to give index number . sometime fabook should be o index sometime twitter will be on 0 index . Please help
socialMediaDetails:
socialMediaDetail: Array(2)
0:
link: "HARIRAM#twitter.com"
name: "twitter"
__typename: "SocialMediaDetail"
__proto__: Object
1:
link: "VarnaHERO#facebook.com"
name: "facebook"
__typename: "SocialMediaDetail"
__proto__: Object
2:
link: "linkedIn#linkedin.com"
name: "linkedIn"
__typename: "SocialMediaDetail"
const socialMediaData=socialMediaDetails.socialMediaDetail;
const Steplabels = socialMediaData.filter((item) => {
return item.name === "twitter"
});
Thanks
You can use find method, like this:
requiredMediaByName = (name) => {
return state.socialMediaDetails.socialMediaDetail.find(data => data.name === name);
};
console.log(requiredMediaByName('facebook'));
Note that find returns the first matching element in the array and it won't check the other elements if you get it on fist match. If you want all the elements to be returned then you should use for loop and get all of them.
There are a few ways this can be achieved - the simplest way would be to use a for .. of loop if you're just looking for the first item matching on name:
function findLinkByName(name) {
for (const item of state.socialMediaDetails.socialMediaDetail) {
if (item.name === name) {
return item.link;
}
}
}
For other cases such as returning a subset of items where multiple matches on name exist, then a simple solution based on filter() and map() could be achieved like this:
function findLinksByName(name) {
return state.socialMediaDetails.socialMediaDetail
.filter(item => item.name === name)
.map(item => item.link);
}
Here's a snippet showing both in action:
var state = {
socialMediaDetails: {
socialMediaDetail: [{
link: "HARIRAM#twitter.com",
name: "twitter"
}, {
link: "VarnaHERO#facebook.com",
name: "facebook"
}, {
link: "linkedIn#linkedin.com",
name: "linkedIn"
}, {
link: "another twitter link",
name: "twitter"
}
]
}
}
/*
Find link of first item matching by name (or undefined if no match found)
*/
function findLinkByName(name) {
for (const item of state.socialMediaDetails.socialMediaDetail) {
if (item.name === name) {
return item.link;
}
}
}
/*
Find links for all items with matching name (or empty array if no
matches found)
*/
function findLinksByName(name) {
return state.socialMediaDetails.socialMediaDetail
.filter(item => item.name === name)
.map(item => item.link);
}
console.log(findLinkByName('twitter'));
console.log(findLinkByName('facebook'));
console.log(findLinksByName('twitter'));
console.log(findLinksByName('facebook'));
Hope that helps!
You could use:
if you only want to know if the value exists or not
var doesExist = arr.some(function(ele) {
return ele.id === '21';
});
If you want to get the value you are searching for:
var data = arr.find(function(ele) {
return ele.id === '21';
});
if (data) {
console.log('found');
console.log(data); // This is entire object i.e. item not boolean
}
I have used following array for this example:
var arr = [];
var item1 = {
id: 21,
label: 'Banana',
};
var item2 = {
id: 22,
label: 'Apple',
};
arr.push(item1, item2);
I have two arrays which I want to compare and check if there is an deleted item in one of these arrays. If there is show me the difference (deleted item)
Here is the code below how I would like to achieve this:
var completedList = [{id:1},{id:2},{id:3},{id:4},{id:7},{id:8}];
var invalidList = [{id:3},{id:4},{id:5},{id:6}];
// filter the items from the invalid list, out of the complete list
var validList = completedList.map((item) => {
console.log(item.id)
return item.id;
//console.log(invalidList.id);
}).filter(item => {
Object.keys(invalidList).map(key => {
console.log(invalidList[key].id)
//return !invalidList[key].id.includes(item.id);
});
})
console.log(validList); // Print [1,2,7,8]
// get a Set of the distinct, valid items
var validItems = new Set(validList);
But this returns me a lot of id's how can I map through both array's and filter on object property id? And only show the difference between these array objects.
So basically what I expect is to see the difference between those arrays so log the differences in id's so in this example: 1,2,5,6,7,8
You could take a Set for getting a difference. For getting the differences from each other (a symmetric difference), you need to get both differences.
const
difference = (a, b) => Array.from(b.reduce((s, v) => (s.delete(v), s), new Set(a))),
getId = ({ id }) => id;
var completedList = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 7 }, { id: 8 }],
invalidList = [{ id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }],
complete = completedList.map(getId),
invalid = invalidList.map(getId),
left = difference(complete, invalid),
right = difference(invalid, complete),
result = [...left, ...right]
console.log(result.join(' '));
console.log(left.join(' '));
console.log(right.join(' '));
This should do the trick.
let completedList = [{id:1},{id:2},{id:3},{id:4},{id:7},{id:8}];
let invalidList = [{id:3},{id:4},{id:5},{id:6}];
// filter the items from the invalid list, out of the complete list
let temp1 = completedList.map(e => e.id);
let temp2 = invalidList.map(e => e.id);
let validList = temp1.filter(e => temp2.indexOf(e) === -1);
// find items only in invalidList
let difference = temp2.filter(e => temp1.indexOf(e) === -1);
console.log(validList); // Print [1,2,7,8]
console.log(difference);
I often rely on lodash implementation for comparison.
In lo dash you can get the job done following manner
_.intersectionWith(arr1, arr2, _.isEqual) - For similarity
_.differenceWith(arr1, arr2, _.isEqual) - for differences
This ans is confined to using a util library to get the job done.
If you are looking for the exact algo I would definitely take some time to develop it and reply as a comment to this post .
Thanks
var completedList = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 7 }, { id: 8 }];
var invalidList = [{ id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }];
//get the items that are in the invalid list but not completed list
var filteredList1 = invalidList.filter((invalidListItem) => !completedList.find((item) => item.id === invalidListItem.id));
//get the items that are in the completed list but not in the invalid list
var filteredList2 = completedList.filter((completedListItem) => !invalidList.find((item) => item.id === completedListItem.id));
//join the two arrays
var difference = filteredList1.concat(filteredList2);
//display the merged array and sort
console.log(difference.sort((item1, item2) => { return item1.id > item2.id ? 1 : item1.id < item2.id ? -1 : 0; }));
//outputs 1,2,5,6,7,8