How To Access All Indexes In Nested Array (Vue-chartjs) - vue.js

so I am trying to display data on my doughnut chart and I am having issues accessing my data from a nested array. When I use the following it just gives me the selected index of the nested array.
So I am wondering is there something else I need to do the computed data or if there is something I am doing wrong.
here is the computed property
countEngagementsByStatus () {
const selectedWorkflow = this.allWorkflows.filter(workflow => workflow.id === this.workflowKey)
const res = selectedWorkflow.map(({statuses, id}) => ({
workflow_id: id,
statuses: statuses.reduce((acc, cur) => {
const count = this.allEngagements.filter(({workflow_id, status}) => workflow_id === id && status === cur.status).length;
acc.push(count);
return acc;
}, [])
}))
return res
},
And on my doughnut chart I am accessing the data. *note removed styling data to clean up the question
datasetsfull() {
return {
labels: this.mapStatuses[0].statuses,
datasets: [
{
label: 'Data One',
data: [
//this is the line I have issues with
this.countEngagementsByStatus[0].statuses[0]
]
}
]
}
},
here is an image of what I am getting
Now If I do this
data: [
this.countEngagementsByStatus[0]
]
I get this as a result however it cannot access the array of numbers shown
So my question is, am I doing something wrong with computed property or am I accessing the data incorrectly or both? Lol
Here is a Js Fiddle To give an idea

So my issue was I was wrapping the data in an array
data: [
this.countEngagementsByStatus[0].statuses
]
I changed it to this
data: this.countEngagementsByStatus[0].statuses

Related

(Vue 3) Error: AG Grid: cannot get grid to draw rows when it is in the middle of drawing rows

-- Initial setup --
Create component
const ButtonAgGrid= {
template: "<button>{{ displayValue }}</button>",
setup(props) {
const displayValue = 'TEST-TEXT';
return {
displayValue,
};
},
};
Register component
<AgGridVue
:components="{
ButtonAgGrid
}"
...
/>
Pass data
const columnDefs = [
{
field: "name"
},
{
field: "button",
cellRenderer: "ButtonAgGrid",
}
]
const rowData = computed(() => {
return {
name: testReactiveValue.value ? 'test', 'test2'
}
})
And when computed "rowData" updated, agGrid send error:
Error: AG Grid: cannot get grid to draw rows when it is in the middle of drawing rows. Your code probably called a grid API method while the grid was in the render stage. To overcome this, put the API call into a timeout, e.g. instead of api.redrawRows(), call setTimeout(function() { api.redrawRows(); }, 0). To see what part of your code that caused the refresh check this stacktrace.
But if we remove cellRenderer: "ButtonAgGrid", all work good
My solution is to manually update rowData.
watchEffect(() => {
gridApi.value?.setRowData(props.rowData);
});
This one works well, but I wish it was originally

this.state return empty array when render

I wanted to display the array series and when I tried to console the array this.state.series in the function it does has the result and the value inside but when I render this.state.series just keep giving empty array. I wonder is it because of the componentDidMount()?
constructor(props){
super(props);
this.state={series:[]}
}
GetTransaction=()=> {
var APIURL="http://10.0.2.2:80/api/getTransaction.php";
var headers={
'Accept':'application/json',
'Content-Type':'application.json'
}
fetch(APIURL,
{
method:'POST',
headers: headers,
})
.then((response)=>response.json())
.then((response)=>
{
this.setState({results:response});
this.state.results[0].map((a) => {
this.state.series.push(a.count)
});
console.log(this.state.series)
})
.catch((error)=>
{
alert("Error"+error);
}
)
}
componentDidMount(){ // runs after the component output has been rendered to the DOM
this.GetTransaction();
}
render(){
console.log(this.state.series)
output
Array []
Array []
Array []
Array []
Array []
Array []
Array []
Array [
"1",
"2",
"1",
"1",
]
There are basically 2 errors in GetTransaction state assignment:
you can't read a state just assigned because this.setState is async. If you want to get the very last value of state you should use this.setState's callback:
this.setState({results:response}, () => {
console.log(this.state.result); //<-- here you have the very last value of result
});
state must be always setted with this.setState: this.state.series.push(a.count) is not good.
So you have to rewrite your code in this way:
...
this.setState({results:response}, () => {
let seriesAppo = [];
this.state.results[0].map((a) => {
seriesAppo.push(a.count);
});
this.setState({series: seriesAppo}, () => {
console.log(this.state.series);
})
});
...
That‘s weird
this.state.results[0].map((a) => {
this.state.series.push(a.count)
});
Don‘t manipulate state that way, only with setState.
const series = response[0];
this.setState({series: series});
Even if you wanna add elements to an array you have to recreate the array. You can achieve this as follows:
const series = response[0];
this.setState({series: […this.state.series, …series]});

How to filter array in json object with computed

fetchData() {
axios.get("api_url").then((response) => {
this.dataArr = response.data;
});
},
I can't do this.dataArr = response.data.items.fruits; because I need to use this somewhere else like this.
dataArr looks like this:
{
"items":{
"fruits":[
{
"name":"banana",
"type":"fruit",
},
{
"name":"kiwi",
"type":"fruit",
},
]
}
I am trying to filter this in computed property:
filterData(){
return this.dataArr.filter((item) => item.name )
}
But I am getting an error saying that this.dataArr is not a function, I need to get access to this.dataArr.items.fruits, but when I write it like that it's not working. Is there way to solve this?
You should get access to the nested fruits array and it seems that you're trying to map that array by returning only the names in this case use map method:
filterData(){
if(this.dataArr.items && this.dataArr.items.fruits){
return this.dataArr.items.fruits.map((item) => item.name )
}else{
return []
}
}

How do I display specific fields from json file in a table with data?

I have around 300 records like this. Now it displays all items in the table. I want only Name,
proteins and kcal to be displayed in my table. How do I do this? I am fetching the list from an API.
[
{
"id":"711113fb-c3d1-46db-9f08-737a66ba643d",
"name":"Banana",
"fats":"0.2",
"carbohydrates":"11.8",
"proteins":"0.8",
"kcal":"46",
"tags":[
],
"tag_ids":[
],
"diet_phases":[
],
"diet_phase_ids":[
],
"product_group_id":"1cad5993-78f8-43b0-a0c5-f6f88fdf53b8",
"product_group_name":"Fruits"
},
productList: (state) => state.products.list,
This.items is an array which holds the items in my table.
mounted: this.fetchProducts().then(() => { this.items = this.productList; }); },
...mapActions ({
fetchProducts: "products/fetch",})
actions: {
fetch({ commit }) {
return api.products.list({}).then(({ data }) => {
commit(SET_LIST, data.results);
});
},
Still missing the template part of your component, and I don't know the bootstrap-vue table. So I assume your this.items just renders out each key of your item object.
So you want to controll what is rendered in the JS code and not the template, you can use the map function. So instead of directly assigning it to this.items, you can do something like this:
this.items = this.productList.map((item) => {
return {
name: item.name,
proteins: item.proteins,
kcal: item.kcal,
};
});

dynamically add new fields to b-table [ Vue.js ]

I am trying to create a table using bootstrap table with fields dynamically added. The fields that will be added will be taken from my api (see code below).
vue.js (jade) - The 2nd template will be the one to render the dynamically added fields but the problem is I can't access the row.item.members because I am not in the row scope. If there is a way to access the row data in the template tag it would be great but I already spent a day and found no luck
b-table(small v-bind:items="plans" v-bind:fields="fields" fixed responsive)
template(slot='bg_action', slot-scope='row')
nuxt-link(:to="'/supply_and_demand/master/'+selected+'/'+row.item.date")
b-button.mr-1(size='sm', variant="primary")
| {{ row.item.date }}
template(v-for="member_info in row.item.members" :slot="id_+ 'member_info.id'" )
| {{ member_info.name }}
my api call (which adds new fields to the table and get the data)
async fetchData(){
let params = {
"q[balancing_group_id_eq]": this.selected
}
this.$restApi.index('bg_members', {params})
.then( (result)=>{
this.fields = [
{ key: 'date', label: '' },
{ key: 'bg_action', label: 'BG' }
]
for(let i = 1; i <= result.length; i++){
this.fields.push({ key: 'id_' + result[i-1].company.id, label: result[i-1].company.name })
}
})
params = {
"q[balancing_group_id_eq]": this.selected,
"q[date_gteq]": this.from,
"q[date_lteq]": this.to
}
this.$axios.$get('/v1/occto/plans', { params })
.then( (result)=>{
console.log("plans")
console.log(this.plans)
this.plans = result
})
}
tldr:I want to access the row data inside the template tag so I can dynamically set the slot which will result to data being displayed properly.