Reading Object returns undefined Angular 4 - javascript

Arr1 [
{id: 300,
uploads: [
{idOne: value},
{idTwo: value}
]
},
{blah: value,
uploads: [
{idOne: value},
{idTwo: value}
]
}
]
This Object is being read like this
this.activatedRoute.parent.params
.switchMap((params: Params) => this.someService.getSubmissions(+params['id']))
.subscribe(submissions => console.log('subs', submissions.map(x=>x)))
results in
The Object as shown above.
And
this.activatedRoute.parent.params
.switchMap((params: Params) => this.someService.getSubmissions(+params['id']))
.subscribe(submissions => console.log('subs', submissions.map(x=>x.id)))
Displays id:300
But when I go
this.activatedRoute.parent.params
.switchMap((params: Params) => this.someService.getSubmissions(+params['id']))
.subscribe(submissions => console.log('subs', submissions.map(x=>x.uploads)))
It logs undefined. And I can not reasonably detect why.
This is within the onInit() of an Angular component.

Try this, updated the above with forEach:-
this.activatedRoute.parent.params.switchMap(params => {
this.someService.getSubmissions(+params['id']))
.subscribe(submissions => {
submissions.forEach(x=>{
if(x.id){
console.log("id",x.id);
}
if(x.uploads){
console.log("uploads",x.uploads);
}
})
});
});

Related

Angular 12 how to return an http get request array of objects and assign to other array of different type using map()

Hey I'm trying to implement a bootstrap5 dropdown following this example: Creating Multi-Select Dropdown with Angular and Bootstrap 5
In that example, to get the data, he uses an app.service and just returns an array of objects:
getFoods(): Food[] {
return [
{
id: 1,
name: 'Grapes'
},
{
id: 2,
name: 'Melon'
},
...
And then in his ngOnInit() calls the getFoods() method and also uses .map() operator because he has to assign to values because the item model has two values:
ngOnInit(): void {
this.items = this.appService.getFoods().map(fruit => ({
id: fruit.id,
name: fruit.name
} as Item));
}
So I'm trying to do hat but with data being fetched from an API endpoint using HTTP GET request.
But I don't know how to use the .map() operator for the http get request:
this.subscription = this.contactSearchService.currentCodes.pipe(
map(
code => (
{
id: code.code,
name: code.code
}
)
)).subscribe(Response => {
this.items = Response
})
It's giving me these errors:
Property 'code' does not exist on type 'ResponsibilityCode[]'.
Type '{ id: any; name: any; }' is missing the following properties from type 'Item[]': length, pop, push, concat, and 26 more.
My http get request function:
private _reponsibilityCodeSource = new BehaviorSubject<ResponsibilityCode[]>([]);
currentCodes = this._reponsibilityCodeSource.asObservable();
getCodes(): void {
this.http.get<ResponsibilityCode[]>('https://localhost:44316/api/SITEContacts/ResponsibilityCode').subscribe(Response => {
this._reponsibilityCodeSource.next(Response);
});
}
I get the data as `JSON` btw.
The rxjs pipe(map(.... code...)) is different than array.map -
pipe(map()) does not operate on each item of an array
So the errors you are getting is because you're swapping out the array of ResponsibilityCode for a single item (code in your code is all the responsibility codes)
Try
this.subscription = this.contactSearchService.currentCodes.subscribe(Response => {
this.items = Response.map(
code => (
{
id: code.code,
name: code.code
}
)
)
})
Your HTTP get returns an Observable of ResponsibilityCode array, so to achieve that you have to map (Array.prototype.map) the items of the array within the RxJS's map operator, like the following:
this.subscription = this.contactSearchService.currentCodes
.pipe(
map((res: ResponsibilityCode[]) =>
res.map((item) => ({
id: item.id,
name: item.name,
}))
)
)
.subscribe((res) => {
this.items = res;
});

use another useeffect result in another

New react developer here, here i have two useEffects, one of them(first one) is an object which contains a 'name' which i want to use in my second useEffect. Second useEffect contains an array of objects, these array of objects has 'billingName' and 'driverName', some of them has same value in them for example driverName: "james". What i want to do is in my second useEffect check if 'name' from first useEffect is same as 'driverName', only then do this 'setOrders(res);
setRenderedData(res);'
my error message: Property 'driverName' does not exist on type...
my object: {
id: "98s7faf",
isAdmin: true,
name: "james"}
my array:  [{billingName: "trump",driverName: "james"}, {billingName: "putin",driverName: "alex"}, {…}, {…}, {…}]
my code:
const [driver, setDriver] = useState<User>();
useEffect(() => {
api.userApi
.apiUserGet()
.then((res: React.SetStateAction<User | undefined>) => {
console.log(res);
setDriver(res);
});
}, [api.userApi]);
useEffect(() => {
api.caApi
.apiCaGet(request)
.then((res: React.SetStateAction<CaDto[] | undefined>) => {
if (driver?.name == res?.driverName) {
setOrders(res);
setRenderedData(res);
console.log(res);
}
});
}, [api.caApi]);
You can call api.caApi in then of api.userApi,
useEffect(() => {
api.userApi.apiUserGet().then((res1?: User ) => {
setDriver(res1);
return api.caApi.apiCaGet(request).then((res?: CaDto[])
=> {
if (res.some(({ driverName }) => driverName === res1?.name)) {
setOrders(res);
setRenderedData(res);
console.log(res);
}
});
});
}, [api.caApi, api.userApi]);

How to get JSON object to React component?

I created a React App with AXIOS. I need to get some JSON data from back end and change the State with that data. When I get the object and mapping to my state, the state is only setting for the last element of the object. So I can only see the last element in the state. How I can get all the elements to the state?
My API call is as follows
API.post('viewallusers', [], config)
.then(({ data }) => {
const allUsers = data.response.AllUsers;
allUsers
.map(user => {
return (
this.setState({
data: [
createData(
user.name,
user.id,
user.email
)
]
})
)
})
})
.catch((err) => {
console.log("AXIOS ERROR: ", err);
})
JSON data:
{response :
{AllUsers :
0 : {name: "Amy", id: 1, email: "myEmail1"},
1 : {name: "Doris", id: 2, email: "myEmail2"},
2 : {name: "Jase", id: 3, email: "myEmail3"}
}
}
I expect the the state "data" is to be set as follows:
data : [
createData("Amy",1,"myEmail1"),
createData("Doris",2,"myEmail2"),
createData("Jase",3,"myEmail3")
]
But the actual state after getting the JSON data is
data : [
createData("Jase",3,"myEmail3")
]
How can I solve this?
You need to first map the data then set entire state.
API.post('viewallusers', [], config)
.then(({ data }) => {
this.setState({
data: data.response.AllUsers.map(user => (createData(user.name, user.id, user.email)))
})
})
Or use callback version of setState and manually merge state.data (NOT recommended in this particular case)
API.post('viewallusers', [], config)
.then(({ data }) => {
data.response.AllUsers.forEach(user => {
this.setState(prev =>
({...prev, data: [prev.data, createData(user.name, user.id, user.email)]})
)
})
})
It probably happens because setState doesn't do a deep merge. So if you have in state
state = {
key1: 123,
key2: {
test1: 1,
test2: 2
}
}
And you do
this.setState({
key2: {
test1: 4
}
})
You will end up with
state = {
key1: 123,
key2: {
test1: 4
}
}
You have to do instead:
this.setState((ps) => ({
key2: {
...ps.key2,
test1: 4
}
}));
Similar approach works if value for key2 is array. Or alternatively you can first map all the data and then do a setState as suggested in other answer.

How can i change JSON structure by group variable? [duplicate]

This question already has answers here:
JavaScript "cannot read property "bar" of undefined [duplicate]
(4 answers)
Closed 4 years ago.
I'm trying to change JSON structure for push to my database
my old JSON :
[
{"name": "nameGallery"},
{"img": "1.jpg"},
{"img": "2.img"}
]
And I want to group "img" variable to "Images" Array like this:
[
{
"name": "nameGallery",
"Images": [
{"img": "1.jpg"},
{"img": "2.img"}
]
}
]
I'm trying to use object.assign to manage it but I don't know why it error.
function getData() {
fetch('text/upload.json').then((res) => res.json())
.then((data) => {
console.log(data);
data = data.map(o => Object.assign({}, o,
{ Images: o.Images.map(({ img }) => ({ img: img })) }
));
})
}
My Result:
In your solution you are calling .map which will create you one array entry for every array entry in your initial data.
As you described, you expect one object as a result and not an array of object. So look at the following :
const data = [{
name: 'nameGallery',
},
{
img: '1.jpg',
},
{
img: '2.img',
},
];
// You want to create a new object using all the others objects
const ret = data.reduce((tmp, x) => {
// If the key below is 'img', we push the object into 'Images'
// void 0 means undefined
if (x.img !== void 0) {
tmp.Images.push(x);
return tmp;
}
// If the key is not 'img'
// We copy the keys into tmp
return {
...tmp,
...x,
};
}, {
// initialize 'Images' key here it won't be undefined
// when pushing the first data
Images: [],
});
console.log(ret);
You can try something like this:
function getData() {
fetch('text/upload.json').then((res) => res.json())
.then((data) => {
const name = data.find(o => !!o.name);
return {
name: name.name,
Images: data.filter(o => !!o.img)
};
})
}

Array prop returns Observer so can't access at [0]

I passed Array but got Observer here's my code:
In Component1
data() {
return {
myWords: [],
}
}
//...
await axios.post(this.serverUrl + router, {
voca: text,
category: this.buttonGroup.category.text
})
.then(res => {
this.myWords.push({
voca: this.voca,
vocaHeader: this.vocaHeader,
category: res.data.savedVoca.category,
date: res.data.savedVoca.date,
id: res.data.savedVoca._id
})
this.myWords.push({voca:"test"})
})
.catch(err => {
console.log(err)
})
In Component2
props: {
myWordsProp: {
type: Array,
default: () => ([])
},
},
mounted() {
console.log(this.myWordsProp)
console.log(this.myWordsProp[0]) //returns undefined
},
And I expected an Array but I get Observer so I can't get values from this.myWordsProp[0] why?
//this.myWordsProp
[__ob__: Observer]
0: {
category: "ETC"
date: "2018-11-21T15:31:28.648Z"
id: "5bf57a503edf4e0016800cde"
voca: Array(1)
vocaHeader: Array(1)
...
}
1: {__ob__: Observer}
length: 2
__ob__: Observer {value: Array(2), dep: Dep, vmCount: 0}
__proto__: Array
//this.myWordsProp[0]
undefined
I found a clue that when I test it outside of axios it worked as I expected.
Vue wraps data and props into reactive objects. Use vue-devtools plugin in your browser as an alternative to viewing the ugly observer in the console.
In your code, the object behaves correctly. It’s only in the console that it ‘looks’ different.
Anyway, you can also click on the ... to expand the node and get the value from the console.
https://github.com/vuejs/vue-devtools
I found a solution It's because of sending props before get data from server.
This is my whole of postVocas function It returns promise
postVocas: function (voca) {
if (!voca || voca.length < 1) return
let router = "/api/voca"
let text = ""
text += `${this.vocaHeader[0].english}, ${this.vocaHeader[0].korean}\n`
voca.forEach((x, index) => {
text += `${voca[index].english}, ${voca[index].korean}\n`
})
return axios.post(this.serverUrl + router, {
voca: text,
category: this.buttonGroup.category.text
}).then(res => {
this.myWords.push({
voca: this.voca,
vocaHeader: this.vocaHeader,
category: res.data.savedVoca.category,
date: res.data.savedVoca.date,
id: res.data.savedVoca._id
})
}).catch(err => {
console.log(err)
})
},
And await till get data from server.
This one is function where execute My postVocas function.
sendVocaToTable: async function () {
let reformedText = this.reformText(this.text)
this.voca = this.formatTextToVoca(reformedText)
await this.postVocas(this.voca)
this.$router.push({
name: 'Table',
params: {
vocaProp: this.voca,
tableHeaderProp: this.vocaHeader
}
})
},

Categories