Remove an array value from within an array of objects - arrays

I have an array that looks like this:
const updatedUsersInfo = [
{
alias: 'ba',
userId: '0058V00000DYOqsQAH',
username: 'ba#dna05.com',
permissionSets: [
'X00e8V000000iE48QAE',
'SCBanquetAccess',
'SCViewOnlyPermission'
]
},
{
alias: 'cs',
userId: '0058V00000DYOqtQAH',
username: 'cs#dna05.com',
permissionSets: [ 'X00e8V000000iE45QAE', 'SCCorpAdmin', 'SEAdmin' ]
}
]
I need to remove from the embedded permissionSets array just the value that starts with 'X00' and looks like this after.
const updatedUsersInfo = [
{
alias: 'ba',
userId: '0058V00000DYOqsQAH',
username: 'ba#dna05.com',
permissionSets: [
'SCBanquetAccess',
'SCViewOnlyPermission'
]
},
{
alias: 'cs',
userId: '0058V00000DYOqtQAH',
username: 'cs#dna05.com',
permissionSets: [ 'SCCorpAdmin', 'SEAdmin' ]
}
]
I have tried many ways to achieve this, however, no matter which way I do it I get a variable 'undefined'
Here is some of the ways I have attempted this:
let test = updatedUsersInfo.forEach((element => element['permissionSets'].filter((permissionSet) => !permissionSet.includes('X00'))));
let test2 = updatedUsersInfo.forEach(element => {
element['permissionSets'].filter((permissionSet) => {
return !permissionSet.includes('X00')
});
});
I have also tried to splice but it also returned an error stating the array could not be spliced. I am primarily a C# developer and typescript is an entirely new ball field for me so any help would be great!

You should use map() and filter() to treat the object as immutable (i.e. a data object should not be changed after its creation).
You should not use includes("X00") as it will also match strings like beforeX00after but you only want to remove those starting with X00. Use startsWith("X00") instead.
const updatedUsersInfo = [
{
alias: "ba",
userId: "0058V00000DYOqsQAH",
username: "ba#dna05.com",
permissionSets: [
"X00e8V000000iE48QAE",
"SCBanquetAccess",
"SCViewOnlyPermission",
],
},
{
alias: "cs",
userId: "0058V00000DYOqtQAH",
username: "cs#dna05.com",
permissionSets: ["X00e8V000000iE45QAE", "SCCorpAdmin", "SEAdmin"],
},
];
const updated = updatedUsersInfo.map((info) => ({
...info,
permissionSets: info.permissionSets.filter((p) => !p.startsWith("X00")),
}));
console.log(JSON.stringify(updated, null, 4))
/* StackOverflow snippet: console should overlap rendered HTML area */
.as-console-wrapper { max-height: 100% !important; top: 0; }
This implementation uses the spread syntax introduced with ES6 as well as rest properties to create new objects from existing object while updating a property.

Related

Error: Response is not a function, when trying to find if the name exists

So I'm using mongodb to fetch some data from the database.
The issue is when I try to check for something in an array
Here is what the structure looks like:
Example array structure
{ // ...
likedPeople: [
{
name: "foo"
image: "test",
},
{
name: "bar",
image: "baz",
}
]
}
This is the array i get Back.
So when i try to find if it includes a certain value,
eg:
const displayName = "foo";
console.log(
likedPeople.map((likedPerson) => {
return likedPerson.name === displayName; // Output: [true, false]
})
);
But then If i again try to do some other method on it like map() or includes(), It breaks the setup:
const response = likedPerson.name === displayName; // Output: [true, false]
response.map((res) => console.log(res)); // Output: ERROR: response.map() is not a function
But the fact is that I am getting an array with the values, so what am I even doing wrong here?
I tried adding an optional chaining response?.map() but still it gave me the same error.
Also the includes() method also returns me the same response.includes is not a function error.
Can anyone help?
Use the some method to check the name exists in likedPeople :
const likedPeople = [
{
name: "foo",
image: "test",
},
{
name: "bar",
image: "baz",
}
];
const displayName = "foo";
const isExist = likedPeople.some(people => people.name === displayName);
console.log(isExist)

typescript how to find inside an array that is already in an array?

I want to find a value inside an array that is already inside an array.
To give an example of my array:
[
{
ConcessionId: 1,
ConcessionName: "Coyotes",
KnownAs: [
{
TeamId: 1,
Name: "Arizona Coyotes",
},
{
TeamId: 2,
Name: "Phoenix Coyotes",
}
]
},
{
ConcessionId: 2,
ConcessionName: "Devils",
KnownAs: [
{
TeamId: 3,
Name: "Colorado Rockies",
},
{
TeamId: 4,
Name: "New-Jersey Devils",
}
]
}
]
What I want is when Icall my function it returns me the team name.
For example, I the parameter value is 3, I want Colorado Rockies as a name:
public getInfo(_TeamID) {
const concession: ConcessionInfo[] = this.concessionList$.filter(function (x) {
x.KnownAs.filter( (y)=> {
y.TeamId= +_TeamID;
return y.Name;
})
})
}
I try so many different way with filter. But never get something good. Never works.
I can make a double .foreach , for each array. but I think a better method exist than making a double loop.
Thanks
Instead of using the filter method (which is in fact working similar as a for loop), you could do forEach on both arrays. For your current data structure, there is no other way around it.
getInfo = (_TeamID) => {
let teamName = '';
this.concessionList$.forEach(entry => {
entry.KnownAs.forEach(team => {
if(team.TeamId === _TeamID){
teamName = team.Name;
return; // break the loop.
}
})
});
return teamName;
}
Here is a working example
https://stackblitz.com/edit/double-for-lopp
EDIT
If you have a look at the polyfill implementation of filter from Mozilla https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter which is in equivalent to the native implementation of filter, you can see that it is looping through the whole array, the same way as a forEach loop. The difference is that the filter method will return a new array based on the boolean condition inside the callback function, while a forEach loop does not return anything.
Assuming myArray is contains the data you provided.
The following code will work if you're using Typescript 3.7 and above.
public getInfo(teamId: number): string | undefined {
const team = this.concessionList$
.map(concession => concession.KnownAs)
.reduce((a, b) => a.concat(b), [])
.find(team => team.TeamId === teamId)
return team ? team.Name : undefined
}
Usage:
this.getInfo(3) // Colorado Rockies
Ok how this work?
You have to understand what is find. For example:
const result = [{name: 'foo', age: 1}, {name: 'bar', age: 2}]
.find(people => people.name === 'foo')
console.log(result) // {name: 'foo', age: 1}

Is there any way to update state by find Item and replace on a nested state?

I am building an order functionality of my modules in the component state on react
so the state object looks like that
"activity": {
"name": "rewwerwer",
"description": "werwerwerwerwer",
"modules": [
{
"name": "Text",
"order": 1,
"module_id": 1612,
},
{
"name": "Text2",
"order" 2,
"module_id": 1592,
}
]
}
handleSortUp = (moduleid ,newOrder) => {
const { modules } = this.state.activity;
const module = modules.find(element => element.module_id === moduleid);//Thios returns the correct object
this.setState({ activity: { ...this.state.activity.modules.find(element => element.module_id === moduleid), order: newOrder } });
}
I tried this but it updates the order field and object
but also removes all other objects from modules array :<
I like just to replace only the order field on each module by module id
and leave rest data there
the required response from the state that i need when the handleSortUp(1612,14); is fired
handleSortUp(1612,2);
{
"name": "rewwerwer",
"description": "werwerwerwerwer",
"modules": [
{
"name": "Text",
"order": 2,
"module_id": 1612,
},
{
"name": "Text2",
"order": 1,
"module_id": 1592,
}
]
}
I can do this on a simple array the question is how to update the State on react
Also the one way to change the order is answered fine but how also to change the field that had that order registered
So when we fire Change Item 1 order to 2 the Item 2 needs to take the Order 1
Thank you
Sure! This would be a great place to use the built-in .map method available for arrays. Consider the following example.
let array = [{order: 1, type: "food"}, {order: 2, type: "notfood"} ]
const newArray = array.map((item) => {
//CHECK TO SEE IF THIS IS THE ITEM WE WANT TO UPDATE
if(item.order == 1){
return {
...item,
newField: "newData"
}
} else {
return item
}
})
Output is:
[{order: 1, type: "food", newField: "newData"}
{order: 2, type: "notfood"}]
So yes you could totally update the module you're looking for without mutating the rest of your array. Then use your findings to update the component state using some good ol spread.
this.setState({
activity: {
...this.state.activity,
modules: newArray}
})
Of course they get all eliminated. Pay attention to what you wrote here:
this.setState({ activity: { ...this.state.activity.modules.find(element => element.module_id === moduleid), order: newOrder } });
What are you doing with that find? Let's see what Array.prototype.find() returns: https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Array/find
It returns an index, why would you insert an index into the state?
The answer partially came from yourfavoritedev.
As he said you can use the built-in Array.prototype.map() and do it like this:
handleSortUp = (moduleid ,newOrder) => {
const { modules } = this.state.activity;
const newModules = modules.map(module => module.module_id === moduleid ? { ...module, order: newOrder } : module)
this.setState({ activity: { ...this.state.activity, modules: newModules } });
}
This should work, let me know but I strongly advice to ask me or search on the web if you don't understand what is happening there (syntactically or semantically speaking).

How can I access all elements with a particular attribute in graphQL?

I have some json data in file called countryData.json structured as so:
{
"info":"success",
"stats":
[{
"id":"1",
"name":"USA",
"type":"WEST"
},
//...
I'm using graphQL to access this data. I have created an object type in the schema for countries using the following:
const CountryType = new GraphQLObjectType({
name: "Country",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
type: { type: GraphQLString },
})
});
I want to write a query that will allow me to access all of the elements of this array that have a certain "name" value(There can be multiple with the same name). I've written the following query, but it only returns the first match in the array:
const RootQuery = new GraphQLObjectType({
name:"RootQueryType",
fields:{
country: {
type: CountryType,
args: { type: { name: GraphQLString } },
resolve(parent, args){
return _.find(countryData.stats, {name: args.name});
}
}
}
});
The "_" comes from const _ = require('lodash');
Also, how can I just get every single item in the array?
I have not recreated the code, therefore I can not check if it would be executed correctly. This is code, that should work in my opinion (without trying). If you want to return array of elements you need to implement https://lodash.com/docs/#filter. Filter will return all objects from stats, which match the argument name. This will return correctly inside resolver function, however, your schema needs adjustments to be able to return array of countries.
You need probably rewrite the arguments as follows as this is probably not correct. You can check out how queries or mutation arguments can be defined https://github.com/atherosai/express-graphql-demo/blob/feature/2-json-as-an-argument-for-graphql-mutations-and-queries/server/graphql/users/userMutations.js. I would rewrite it as follows to have argument "name"
args: { name: { type: GraphQLString } }
You need to add GraphQLList modifier, which defines, that you want to return array of CountryTypes from this query. The correct code should look something like this
const RootQuery = new GraphQLObjectType({
name:"RootQueryType",
fields:{
country: {
type: CountryType,
args: { name: { type: GraphQLString } },
resolve(parent, args){
return _.find(countryData.stats, {name: args.name});
}
},
countries: {
type: new GraphQLList(CountryType),
args: { name: { type: GraphQLString } },
resolve(parent, args){
return _.filter(countryData.stats, {name: args.name});
}
}
}
});
Now if you call query countries, you should be able to retrieve what you are expecting. I hope that it helps. If you need some further explanation, I made the article on implementing lists/arrays in GraphQL schema as I saw that many people struggle with similar issues. You can check it out here https://graphqlmastery.com/blog/graphql-list-how-to-use-arrays-in-graphql-schema
Edit: As for the question "how to retrieve every object". You can modify the code in resolver function in a way, that if the name argument is not specified you would not filter countries at all. This way you can have both cases in single query "countries".

How can I Add and Delete nested Object in array in Angularjs

heres my output Image html How can I delete Object in array and push when adding some Data
angular.module('myApp.Tree_Service', [])
.factory('TreeService', function() {
var svc = {};
var treeDirectories = [
{
name: 'Project1',
id: "1",
type: 'folder',
collapse: true,
children: [
{
name: 'CSS',
id: "1-1",
type: 'folder',
collapse: false,
children: [
{
name: 'style1.css',
id: "1-1-1",
type: 'file'
},
{
name: 'style2.css',
id: "1-1-2",
type: 'file'
}
]
}
]
}
];
svc.add = function () {}
svc.delete = function (item, index) { }
svc.getItem = function () { return treeDirectories; }
return svc;
});
})();
I'm Newbee in Angularjs and I don't know how much to play it.
Hopefully someone can help me. Im Stucked.
Well you can delete any object by just usingdelete Objname.property
So for example you want to delete Children in treeDirectories first index object you can use delete treeDirectories[0].children if you want to delete children inside children then delete treeDirectories[0].children[0].children
if you want to remove an index from an array in lowest level children then
treeDirectories[0].children[0].children.splice(index,1)
for pushing data is for object you can directly assign value to the property you want
treeDirectories[0].children[0].newproperty = "check"
And for array you can
treeDirectories[0].children[0].children.push(object)

Resources