How to retrieve value of key from an object inside an array - arrays

I'm trying to retrieve the merchant name from within the following array:
[
{
"model": "inventory.merchant",
"pk": 1,
"fields": {
"merchant_name": "Gadgets R Us",
"joined": "2020-01-06T07:16:17.365Z"
}
},
{"model": "inventory.merchant", "pk": 2, "fields": {"merchant_name": "H&M", "joined": "2020-01-07T22:21:52Z"}},
{"model": "inventory.merchant", "pk": 3, "fields": {"merchant_name": "Next", "joined": "2020-01-07T22:22:56Z"}},
{"model": "inventory.merchant", "pk": 4, "fields": {"merchant_name": "Jill Fashion", "joined": "2020-01-07T22:26:48Z"}}
]
I'm using vuejs and have used axios to fetch the above data via an api. I put in an array called merchants[]. I'm able to get any item I want from within my html using v-for i.e.
<div v-for="merchant in merchants">
<p>{{ merchant.fields.merchant_name }}</p>
</div>
However, in my .js file, doing the following does not work:
console.log(this.merchants[0].fields.merchant_name)
I get the following error in my console:
vue.js:634 [Vue warn]: Error in render: "TypeError: Cannot read property 'fields' of undefined"
Please help
Edit:
This is my .js file. I try to log the merchants name in the console from the merchantName() computed property:
new Vue({
delimiters: ['[[', ']]'],
el: "#inventory",
data: {
gallery: true,
inCart: false,
shipping: false,
galleryView: "zoom",
ref: "",
cart: [],
isSelected: false,
selectedClass: "in_cart",
shippingCost: 2000,
inventory: [],
merchants: [],
},
methods: {
zoomGallery(){
this.galleryView = "zoom"
},
back(){
this.gallery = "thumbnail"
},
addToCart(name, merchant, price, qty, image, id){
var itemClone = {}
itemClone = {
"merchant": merchant,
"name": name,
"price": price,
"qty": qty,
"image": "/media/" + image,
"id": id,
}
this.cart.push(itemClone)
this.isSelected = true
},
removeFromCart(index){
this.cart.splice(index, 1)
},
deleteFromCart(id){
console.log(id)
// right now, any caret down button deletes any input
// I need to use components to prevent that
if (this.cart.length > 0){
index = this.cart.findIndex(x => x.id === id)
this.cart.splice(index, 1)
}
},
viewCart(){
this.gallery = false
this.shipping = false
this.inCart = true
},
viewShipping(){
this.gallery = false
this.shipping = true
this.inCart = false
}
},
computed: {
itemsInCart(){
return this.cart.length
},
subTotal(){
subTotal = 0
inCart = this.cart.length
for (i=0; i<inCart; i++) {
subTotal += Number(this.cart[i].price)
}
return subTotal
},
checkoutTotal(){
return this.subTotal + this.shippingCost
},
merchantName(){
console.log(this.merchants[0])
},
},
beforeMount() {
axios
.get("http://127.0.0.1:8000/get_products/").then(response => {
(this.inventory = response.data)
return axios.get("http://127.0.0.1:8000/get_merchants/")
})
.then(response => {
(this.merchants = response.data)
})
},
});
Edit:
Response from console.log(this.merchants) is:
[__ob__: Observer]
length: 0
__ob__: Observer
value: Array(0)
length: 0
__ob__: Observer {value: Array(0), dep: Dep, vmCount: 0}
__proto__: Array
dep: Dep
id: 16
subs: Array(0)
length: 0
__proto__: Array(0)
__proto__: Object
vmCount: 0
__proto__:
walk: ƒ walk(obj)
observeArray: ƒ observeArray(items)
constructor: ƒ Observer(value)
__proto__: Object
__proto__: Array

Why you are trying to console.log this.merchants in computed property. Check for computed property of vuejs here.
Your data is empty before data from API call even come. So that's why your this.merchants is empty.
You can get you this.merchants value by using a method and run it after your api call or watching that like this:
watch: {
merchants: function () {
console.log(this.merchants)
}
}
It will console this.merchants array everytime a change happens in it.

Related

reactjs & woocommerce rest api - add item to cart with selected options' value

I am working on a react frontend for a woocommerce shop and I am currently trying to add an item to the cart with the selected option values ie size and color.
My current api call -
const AddToCart = async (id) => {
let config = {
method: "post",
url: "/wp-json/wc/store/v1/cart/add-item",
data: {
id : id,
quantity: 1,
attributes: [
{
color: color
},
{
size: size
}]
}
}
const resp = await axios(config).then((response) => {
console.log(response.data)
})
.catch((error) => {
console.log(error.response.data);
});
}
In the docs it says -
Chosen attributes (for variations) containing an array of objects with
keys attribute and value
However what I've tried is giving me this error -
code: "woocommerce_rest_variation_id_from_variation_data"
data: {status: 400}
message: "No matching variation found."
Example json response for single product -
{
"id": 933,
.......
"attributes": [
{
"id": 1,
"name": "Size",
"position": 0,
"visible": false,
"variation": true,
"options": [
"2XL",
"3XL",
"4XL",
"5XL",
"L",
"M",
"S",
"XL",
"XS"
]
}
],
"default_attributes": [],
"variations": [
936,
937,
938,
939,
940,
941,
942,
943,
944
],
......
You have to pass the data like this:
data: {
id: id,
quantity: 1,
variation: [
{
attribute: "color"
value: color,
},
{
attribute: "size"
value: size,
}
]
}
As per documentation, variation accepts the array of objects and objects should have keys attribute and value.
what's wrong with this
[{ attribute: 'color', value : selectedColor },{ attribute : 'size', value : selected }]

Using useListController inside ListContextProvider doesn't provide the data

I am using react-admin and I am encountering the Problem that useListController does not provide any data inside ListContextProvider even though useListContext does.
const query = useQuery({
type: 'getList',
resource: 'dashboard/summary',
payload: {
pagination: { page, perPage },
sort: { field: 'createdAt', order: 'DESC' },
filter
},
});
// more code ....
return (
<ListContextProvider
value={{
...query,
setPage,
basePath,
data: keyBy(query.data, 'id'),
ids: query.data.map(({ id }) => id),
currentSort: { field: 'id', order: 'ASC' },
selectedIds: [],
resource,
page,
perPage,
setFilters
}}
>
<SummaryList onSearch={onSearch} filter={filter} />
</ListContextProvider>
);
Inside SummaryList
const context = useListContext();
const cp = useListController(context);
console.log(context);
console.log(cp);
The controller Object
basePath: "/dashboard/summary"
currentSort: Object { field: "id", order: "ASC" }
data: Object { }
defaultTitle: "Dashboard/summaries"
displayedFilters: Object { }
error: null
exporter: function defaultExporter(data, _, __, resource)
filter: undefined
filterValues: Object { }
hasCreate: undefined
hideFilter: function hideFilter(filterName)​
ids: Array []
loaded: true
loading: false
onSelect: function select(newIds)​
onToggleItem: function toggle(id)​
onUnselectItems: function clearSelection()
page: 1
perPage: 10
resource: "dashboard/summary"
selectedIds: Array []
setFilters: function setFilters(filter, displayedFilters, debounce)​
setPage: function setPage(newPage)​
setPerPage: function setPerPage(newPerPage)​
setSort: function setSort(sort, order)​
showFilter: function showFilter(filterName, defaultValue)
total: undefined
The context Object
{
"data": {
// the data which I omitted
},
"total": 4,
"loading": false,
"loaded": true,
"basePath": "/dashboard/summary",
"ids": [
"2021-05-01",
"2021-05-02",
"2021-05-03",
"2021-05-04"
],
"currentSort": {
"field": "id",
"order": "ASC"
},
"selectedIds": [],
"resource": "dashboard/summary",
"page": 1,
"perPage": 10
}
How am I supposed to use useListController ?
useListController takes the List props (and location parameters), uses it to fetch data from the dataProvider, and passes it to the ListContext.
By calling useListContext(), you're accessing the values and callbacks built by useListController.
In your example, you're building the ListContext by hand, so you don't need useListController at all.

React Axios Get Call to Output JSON Format

I am performing an Axios get call in a React Component to retrieve JSON info. That function is working great. Within the JSON is a label for various network ports, which are returning as an array in my axios call. These are ultimately going to be displayed as nodes on a d3 graph. My issue is that I need to output the data pulled from the get call into the following format:
nodes: [
{ id: 'JSON data.label here' },
{ id: 'JSON data.label here' },
{ id: 'JSON data.label here' },
{ id: 'JSON data.label here' },
{ id: 'JSON data.label here' }
]
So the full component for the graph to read is:
export const data = {
nodes: [
{ id: 'JSON data.label here' },
{ id: 'JSON data.label here' },
{ id: 'JSON data.label here' },
{ id: 'JSON data.label here' },
{ id: 'JSON data.label here' }
]
}
Here is the format of the Axios get I am using:
axios.get(`NetworkConstruct.json`)
.then(res => {
const names = res.data.items;
this.setState({ names });
});
Here is a sample output I am receiving (there are 11 of these):
{id: "5bc0860c-ece1-461c-bac0-b155a3cacd82", label: "80.107.0.212",
resourceTypeId: "tosca.resourceTypes.NetworkConstruct", productId:
"5bc0835c-6cfa-486e-8429-a59eaf4118bc", tenantId: "393fa8da-61fd-458c-80f9-
ce92d0ef0330", …}
The data has to be in this EXACT format or the graph won't read it. I'm guessing I'll need to do an initial map function but am stuck on how to arrange it. I cannot have any divs or quotes in my output. Is this doable? I have scoured the boards and Google for a couple of days and can't make this work yet.
Here is the object I am receiving from the GET request.
{
"id": "5bd2c6ef-6009-4b90-9156-62168f3c6293",
"resourceId": "5bd0ba82-2994-455d-8716-2adb5694d6f0",
"interface": "getGraph",
"inputs": {},
"outputs": {
"graph": {
"nodes": [
{
"id": "5bcdf06c-dd53-4335-840f-55a4b8d85a2d",
"name": "asw-lab9306b",
"ports": {
"GigabitEthernet3/0/8": "5bd1777f-0ab9-4552-962b-9e306ce378ab",
"GigabitEthernet2/0/15": "5bd1777e-119c-44e8-ba69-0d86a481c0f5",
"GigabitEthernet3/0/47": "5bd17783-be94-4aaf-8858-70e4eb3d02dc",
"GigabitEthernet2/0/13": "5bd17783-ed99-453f-a958-f764edaa8da8"
}
}
],
"links": [
{
"a": "5bd1a467-13f2-4294-a768-561187b278a8",
"z": "5bd17770-2e6c-4c37-93c8-44e3eb3db6dd",
"layer": "ETHERNET"
},
{
"a": "5bd1776e-c110-4086-87d6-a374ccee419a",
"z": "5bd17770-83ee-4e10-b5bb-19814f9f5dad",
"layer": "ETHERNET"
}
]
}
},
"state": "successful",
"reason": "",
"progress": [],
"providerData": {},
"createdAt": "2018-10-26T07:49:03.484Z",
"updatedAt": "2018-10-26T07:49:25.425Z",
"resourceStateConstraints": {},
"executionGroup": "lifecycle"
}
The info I need is the nodes ID. There are eleven of them in the full object.
You can map an array of objects to another array of objects in your format with Array.prototype.map(). Assuming that data is the list of objects from your response:
class Graph extends React.Component {
state = {
nodes: null,
};
componentDidMount() {
axios.get('the url').then(response => {
const nodes = response.data.outputs.graph.nodes;
this.setState({nodes});
});
}
render() {
const {nodes} = this.state;
if (!nodes) return 'Loading...'
return <TheD3ComponentYouUse nodes={nodes} />;
}
}

Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays. Angular

html
<div class="py-4" *ngFor="let data of Question; let i = index">
{{data | json}}
</div>
component.ts
ngOnInit(){
this.showQuestion();
}
Question: any [];
showQuestion() {
const Entity = new TaskViewEntity(someParameter, 'QuestionDetails');
this.serviceParameter.TaskApi(Entity.requestFormat).subscribe(res => {
if (res['result'].questionDetails !== undefined) {
const arr = res['result'].questionDetails.questions;
this.Question = arr.map(item => {
return {
'counter': 1,
'answer': item.answer,
'approveFlag': item.approveFlag,
'options': item.options,
'question': item.question,
'questionId': item.questionId,
'questionType': item.questionType,
'subQuestion': item.subQuestion
};
});
}
});}
service.ts
public TaskApi = (data) => {
const url = 'URL';
return this.http.post(url, data);
}
Json
"questions": [
{
"questionId": 44,
"question": "abc",
"questionType": "checkbox",
},
{
"questionId": 44,
"question": "abc",
"questionType": "checkbox",
},
{
"questionId": 44,
"question": "abc",
"questionType": "checkbox",
},
]
After using console.log(this.Question), i get this result
(3) [{…}, {…}, {…}]
0: {counter: 1, answer: "", approveFlag: true, options: {…}, question: "Please confirm the address of the property is", …}
1: {counter: 1, answer: "", approveFlag: true, options: {…}, question: "Please confirm the name of the seller?", …}
2: {counter: 1, answer: "", approveFlag: true, options: {…}, question: "Please confirm the number of sellers/partners?", …}
The above mentioned code not working it shows the error in my console which is : Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays. Angular. I am not able to access questions.
I think you have not initialised the array questions in the first place , you are initialising it in subscribe , so until then it is uninitialised , can you try doing :
Question: any[] = [];

Count an array inside an array and then sum them MongoDB NodeJS

I have an object that has an array of page objects and each page object has an array of questions.
Ex object:
{
Id: 1,
UserId: 14,
Deleted: false,
Collaborators: [],
Title: "Awesome",
Pages: [{
Id: 1,
Title: 'Jank',
Questions: [
{ Id: 1, Content: 'Ask me about it' },
{ Id: 2, Content: 'Ask me about it again' }
]
}, {
Id: 2,
Title: 'Janker',
Questions: [
{ Id: 1, Content: 'Tell me about it' },
{ Id: 2, Content: 'Tell me about it again' }
]
}]
}
What I am trying to do is to get a count of all the questions for the entire bas object. I am not sure how to do that. I have tried to use aggregate and $sum the total questions and then do another function to $sum those all together to get a total for the entire object. Unfortunately my $sum is not working like I thought it would.
Ex code (nodejs):
var getQuestionCount = function(id) {
var cursor = mongo.collection('surveys').aggregate([{
$match: {
$or: [{
"UserId": id
}, {
"Collaborators": {
$in: [id]
}
}]
}
}, {
$match: {
"Deleted": false
}
}, {
$unwind: "$Pages"
},
{ $group: { _id: null, number: { $sum: "$Pages.Questions" } } }
], function(err, result) {
//This log just gives me [object Object], [object Object]
console.log('q count ' + result);
});
}
Any idea how to do this? My end result from the example object above would ideally return 4 as the question count for the whole object.
I'd try following shell query.
db.collection.aggregate([
// filter out unwanted documents.
{$match:{Id: 1}},
// Unwind Pages collection to access Questions array
{$unwind:"$Pages"},
// Count items in Questions array
{$project:{count: {$size:"$Pages.Questions"}}},
// Finally sum items previously counted.
{$group:{_id:"$_id", total: {$sum: "$count"}}}
])
Based on your sample document, it should return correct count of Questions.
{
"_id" : ObjectId("57723bb8c10c41c41ff4897c"),
"total" : NumberInt(4)
}

Resources