So i'm making a react app and I have a list of projects that use specific technologies. I want the user to be able to be able to say i'm looking for a project that uses 'a', 'b', and 'c' technologies via some checkboxes (maybe) and the list of projects will automatically update. Should i just be using vanilla javascript for this (to sort through an array of objects) or is there an easier way to do it?
If this should be done via vanilla javascript, can someone give me a little direction please. was able to do this successfully search for just one 'technology' but couldn't quite get it done searching for multiple technologies.
Example data to be below.
const projects = [{
name: 'projecta',
technologies: ['a', 'b', 'f'],
link: 'www.example'
},
{
name: 'projectb',
technologies: ['c', 'd', 'e'],
link: 'www.example'
},
{
name: 'projectc',
technologies: ['a', 'b', 'c', 'd', 'e'],
link: 'www.example'
}];
So i'm making a react app and I have a list of projects that use specific technologies. I want the user to be able to be able to say i'm looking for a project that uses 'a', 'b', and 'c' technologies via some checkboxes (maybe) and the list of projects will automatically update. Should i just be using vanilla javascript for this (to sort through an array of objects) or is there an easier way to do it?
If this should be done via vanilla javascript, can someone give me a little direction please. was able to do this successfully search for just one 'technology' but couldn't quite get it done searching for multiple technologies.
Example data to be below.
const projects = [{
name: 'projecta',
technologies: ['a', 'b', 'f'],
link: 'www.example.'
},
{
name: 'projectb',
technologies: ['c', 'd', 'e'],
link: 'www.example.'
},
{
name: 'projectc',
technologies: ['a', 'b', 'c', 'd', 'e'],
link: 'www.example.'
}];
Share
Improve this question
edited Sep 7, 2017 at 11:26
Kalamarico
5,69622 gold badges56 silver badges73 bronze badges
asked Sep 7, 2017 at 10:43
D. WallD. Wall
771 gold badge1 silver badge17 bronze badges
6 Answers
Reset to default 3You could use a destructuring while filtering with checking all wanted technologies.
const
projects = [{ name: 'projecta', technologies: ['a', 'b', 'f'], link: 'www.example.' }, { name: 'projectb', technologies: ['c', 'd', 'e'], link: 'www.example.' }, { name: 'projectc', technologies: ['a', 'b', 'c', 'd', 'e'], link: 'www.example.' }],
search = ['c', 'e'],
result = projects.filter(({ technologies }) =>
search.every(s => technologies.includes(s)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you have multiple checkboxes you will get an array which contains the value of all selected checkboxes. Filter the array based one or multiple values will work like this:
const projects = [
{
name: 'projecta',
technologies: ['a', 'b', 'f'],
link: 'www.example.'
},
{
name: 'projectb',
technologies: ['c', 'd', 'e'],
link: 'www.example.'
},
{
name: 'projectc',
technologies: ['a', 'b', 'c', 'd', 'e'],
link: 'www.example.'
}
];
const search = ['c', 'e'];
const result = projects.filter(project => {
return search.every(s => project.technologies.includes(s));
});
// or
const result2 = projects.filter(project => {
return !search.some(s => project.technologies.indexOf(s) === -1);
});
console.log(result);
console.log(result2);
Yes you can do it using only vanilla JS, you can profit from Array's buil-in methods to do it.
You can use a bination of .filter()
and .some()
methods to filter your array based on the specified technologies list.
This is how should be your code:
const techs = ['a', 'c'];
var filtered = projects.filter(function(p){
return !techs.some(function(t){
return p.technologies.indexOf(t) === -1;
});
});
Demo:
const projects = [
{
name: 'projecta',
technologies: ['a', 'b', 'f'],
link: 'www.example.'
},
{
name: 'projectb',
technologies: ['c', 'd', 'e'],
link: 'www.example.'
},
{
name: 'projectc',
technologies: ['a', 'b', 'c', 'd', 'e'],
link: 'www.example.'
}
];
const techs = ['a', 'c'];
var filtered = projects.filter(function(p){
return !techs.some(function(t){
return p.technologies.indexOf(t) === -1;
});
});
console.log(filtered);
Explanation:
We use filter()
method to loop over the array filter its elements and in its callback function we use .some()
method to test over the iterated project technologies
to make sure they're all among of the given technologies list.
Assuming you store the selected technologies in an array, you could simply loop through each project with filter()
and return those that have at least one of the techs.
In the snippet below we iterate through each project with filter
, meaning we create an array with items that satisfy the criteria in the callback.
The callback does another filter for each tech of the current project, and returns the length of the filtered array. If no tech of the current project matches your selection, the array length is zero which is a falsy value and the whole object won't be returned to the new array.
For example:
let selectedTechs = ['a', 'b']; //selected techs
const projects = [
{
name: 'projecta',
technologies: ['a', 'b', 'f'],
link: 'www.example.'
},
{
name: 'projectb',
technologies: ['c', 'd', 'e'],
link: 'www.example.'
},
{
name: 'projectc',
technologies: ['a', 'b', 'c', 'd', 'e'],
link: 'www.example.'
}
];
let arr = projects.filter(
(item) => item.technologies.filter((x) => selectedTechs.includes(x)).length
);
console.log(arr); //returns the 1st and 3rd project object.
and a demo in React:
class MyApp extends React.Component {
constructor() {
super();
this.state = {
technologies: ['a', 'b', 'c', 'd', 'e', 'f'],
checkedTechs: [],
projects: [
{
name: 'projecta',
technologies: ['a', 'b', 'f'],
link: 'www.example.'
},
{
name: 'projectb',
technologies: ['c', 'd', 'e'],
link: 'www.example.'
},
{
name: 'projectc',
technologies: ['a', 'b', 'c', 'd', 'e'],
link: 'www.example.'
}
]
};
}
checkTech = (name) => {
let arr = this.state.checkedTechs.slice();
if(arr.includes(name)) {
arr.splice(arr.indexOf(name), 1);
} else {
arr.push(name);
}
this.setState({checkedTechs: arr});
}
render() {
let {technologies, checkedTechs, projects} = this.state;
return(
<div>
<div>
{technologies.map(
(item) => <label key={item}>{item}<input value={checkedTechs.indexOf(item)>-1} onChange={this.checkTech.bind(this, item)} type="checkbox" /></label>
)}
</div>
<ul>
{this.state.projects.filter(
(item) => item.technologies.filter((x) => checkedTechs.includes(x)).length
).map(
(item) => <li key={item.name}>{item.name}</li>
)}
</ul>
</div>
);
}
}
ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.js"></script>
<div id="app"></div>
The above is to show project that include the selected techs. If you want to select projects that have exactly the selected techs, replace the filter logic with:
(item) => item.technologies.join(',') === checkedTechs.sort().join(',')
You can use javascript for this. Say, in each click of checkbox
your checkbox value is saved in choice then you can get the objects like this,
const projects = [
{
name: 'projecta',
technologies: ['a', 'b', 'f'],
link: 'www.example.'
},
{
name: 'projectb',
technologies: ['c', 'd', 'e'],
link: 'www.example.'
},
{
name: 'projectc',
technologies: ['a', 'b', 'c', 'd', 'e'],
link: 'www.example.'
}
];
var choice = 'e';
var res= projects.filter((x)=>{
if(x.technologies.indexOf(choice) !== -1){
return x;
}
});
console.log(res);
I've found something that works. best solution?
const checkFor = ['a', 'b'];
const winners = projects.filter(project => {
return checkFor.every(function(val) {
return project.technologies.indexOf(val) !== -1;
});
});
console.log('winners: ', winners);