How to make ref in component link to component data? - vue.js

I am using https://github.com/r3code/vue-vis-network
I am getting error: Cannot read property 'hasChildNodes' of undefined
My component code is:
<template>
<el-container >
<el-main>
<network ref="network" :nodes="nodes" :edges="edges" :options="options"> </network>
<button #click="get_data">GetData</button>
</el-main>
</el-container>
</template>
<script>
export default {
components: { Notification },
data () {
return {
nodes: [],
edges: [],
options: []
}
},
methods:
{
get_data()
{
axios.get(base_url + '/graph')
.then((response) => {
this.nodes = response.data.nodes;
this.edges = response.data.edges;
}).catch((error) => { console.log(error); });
}
},
}
</script>
index.js:
Vue.component('network', new vueVisNetwork.Network);
I suppose that there is problem that it's attempt to access to data placed in #app. How I can say him that he should use data declared in component?
Actual data example:
nodes : [
{id: 1, label: 'Fooo"', group: "company"},
{id: 2, label: 'Baaar', group: "owner"},
],
edges : [
{from: 1, to: 2},
],
possible related issue https://github.com/crubier/react-graph-vis/issues/57

Related

Unable to update Apexchart's category (x-axis label) dynamically in vue

I am using Apexchart's bar chart and noticed that I am not able to change the x-axis's labels, ie the categories. Below is the component:
<template>
<div>
{{magnitudeByFreq}}
{{chartOptions}}
<apex-chart width="500" type="bar" :options="chartOptions" :series="series"></apex-chart>
</div>
</template>
<script>
export default {
props: {
processedMouseData: null,
gradientCountByType: null,
magnitudeByFreq: null,
},
data: function() {
return {
chartOptions: {
chart: {
id: 'vuechart-example'
},
xaxis: {
categories: []//['Positive', 'Neutral', 'Negative']
}
},
series: [{
name: 'series-1',
data: []
}]
}
},
mounted() {
},
watch: {
gradientCountByType: function() {
console.log(this.series.data)
this.gradientCountByType ? this.series[0].data = this.gradientCountByType : console.log("Not working")
this.gradientCountByType ? this.chartOptions.xaxis.categories = ['Positive', 'Neutral', 'Negative'] : console.log("No xaxis")
},
magnitudeByFreq: function() {
this.magnitudeByFreq ? this.series[0].data = Object.values(this.magnitudeByFreq) : console.log("ABX")
this.magnitudeByFreq ? this.chartOptions.xaxis.categories = Object.keys(this.magnitudeByFreq) : console.log("ABA")
}
}
};
</script>
Currently the categories is set to []. This is because I want it to be filled by different data depending on which prop is using it. ie gradientCountByType or magnitudeByFreq.
The two lines below which are supposed to set the category:
this.gradientCountByType ? this.chartOptions.xaxis.categories = ['Positive', 'Neutral', 'Negative'] : console.log("No xaxis")
this.magnitudeByFreq ? this.chartOptions.xaxis.categories = Object.keys(this.magnitudeByFreq) : console.log("ABA")
They don't seem to update the category at all. I should however mention that what gets displayed in the template {{magnitudeByFreq}} and {{chartOptions}}, do reflect there is a change in the category variable:
{{chartOptions}} shows:
{ "chart": { "id": "vuechart-example" }, "xaxis": { "categories": [ "Positive", "Neutral", "Negative" ], "convertedCatToNumeric": false } }
and
{ "chart": { "id": "vuechart-example" }, "xaxis": { "categories": [ "+0", "+100", "+1000", "+2000" ], "convertedCatToNumeric": false } }
Why is the categories attribute not displaying correctly? For whatever reason, the categories are showing numbers.
My guess is by changing the data attribute doesn't actually update the chart.
Instead we should create a reference to the chart:
<apex-chart ref="radar" type="radar" height="350" :options="chartOptions" :series="series"></apex-chart>
Then we can update the data with updateSeries method and update the chartOptions with updateOptions method:
this.$refs.radar.updateSeries([{
name: 'Series 1',
data: [your_new_data_here] //ie [1,2,3,4]
}])
this.$refs.radar.updateOptions({
xaxis: {
categories: [your_new_categories_here] //ie ["a","b","c","d"]
}
})
<apex-chart ref="chart" :options="options" :series="series"/>
Chart component has refresh function. So we can re-render the chart.
this.series[0].data = [yourData];
this.options.xaxis.categories = [yourCategories]
this.$refs.chart.refresh();

How to make nested properties reactive in Vue

I hava a component with complex nested props:
<template>
<div>
<a-tree :tree-data="data" :selected-keys="[selectedKey]" #select="onSelect" />
<div>
<a-input v-model="sheet[selectedKey].tableName" />
<ux-grid ref="previewTable">
<ux-table-column v-for="field in sheet[selectedKey].fields"
:key="field.name" :field="field.name">
<a-input slot="header" v-model="field.label" />
</ux-table-column>
</ux-grid>
</div>
</div>
</template>
<script>
export default {
props: {
previewData: { type: Array, default: () => [] }
},
data () {
return {
data: this.previewData,
selectedKey: '0-0-0',
sheet: { 'none': { tableName: null, fields: [] } }
}
},
created () {
this.data.forEach((file, fid) => {
file.sheets.forEach((sheet, sid) => {
this.$set(this.sheet, `0-${fid}-${sid}`, {
tableName: sheet.label,
fields: sheet.fields.map(field => ({ ...field }))
})
})
})
},
mounted () {
this.$refs.previewTable.reloadData(this.data[0].sheets[0].data)
},
methods: {
onSelect ([ key ], { node }) {
if (key !== undefined && 'fields' in node.dataRef) {
this.selectedKey = key
this.$refs.previewTable.reloadData(node.dataRef.data)
} else {
this.selectedKey = 'none'
this.$refs.previewTable.reloadData()
}
}
}
}
</script>
And previewData props is something like:
{
name: "example.xlsx",
filename: "80b8519f-f7f1-4524-9d63-a8b6c92152b8.xlsx",
sheets: [{
name: "example",
label: "example",
fields:[
{ label: "col1", name: "col1", type: "NUMBER" },
{ label: "col2", name: "col2", type: "STRING" }
]
}]
}
</script>
This component allows user to edit the label properties. I have to make Object sheet reactive to user input, and I tried $set and Object.assign, it works for sheets.label but fields[].label is still not reactive.
I wish to know what would be the declarative (and optimal) solution for it
You might need a watcher or computed property in React for previewData to be changed.

Vue.js access variable from method

I try to fetch stocks data from an API. This data should be used to create a chart.js graph.
how do I access in vue.js data to generate a chart.js line chart from the methods http(axios) call?
Is it possible to access the data directly in the mounted component or should I define a const in the section and create the variables there?
<template>
<select v-model="selected">
<option v-for="option in options" :value="option.value">
{{ option.text }}
</option>
</select>
<div>Selected: {{ selected }}</div>
<div>
<canvas id="myChart" height="200" width="650"></canvas>
</div>
<script>
export default {
mounted() {
const ctx = document.getElementById("myChart");
const myChart = new Chart(ctx, {
type: "line",
data: {
labels: [prices[0].date],
datasets: [
{
label: 'Dataset msft',
data: prices[0].price
},
{
label: 'Dataset google',
data: prices[1].price
},
],
},
});
},
data() {
return {
selected: "",
prices: [],
options: [
{ text: "msft", value: "msft" },
{ text: "GOOGL", value: "GOOGL" },
],
};
},
watch: {
selected: function () {
this.getPrice();
},
},
methods: {
getPrice: function () {
var this_ = this;
axios
.get(
"https://site/...."
)
.then((response) => {
// JSON responses are automatically parsed.
this_.prices = response.data;
})
},
},
};
</script>
Yes, you can access variables in data() from mounted().
You need to prepend variables with this. when using the Options API
ex: this.prices[0].price
As you are putting watcher on selected but I did not see any changes in the selected variable in your code. As per my understanding you are making an API call to get the graph data based on the selected option.
If Yes, Instead of generating a chart in mounted you can generate it inside your getPrice() method itself based on the response. It should be :
methods: {
getPrice: function () {
var this_ = this;
axios
.get(
"https://site/...."
)
.then((response) => {
this.generateChart(response.data);
})
},
generateChart(prices) {
const ctx = document.getElementById("myChart");
const myChart = new Chart(ctx, {
type: "line",
data: {
labels: [prices[0].date],
datasets: [
{
label: 'Dataset msft',
data: prices[0].price
},
{
label: 'Dataset google',
data: prices[1].price
}
]
}
});
}
}
Here, a very basic example:
<script>
export default {
async mounted() {
await this.$nextTick();
const ctx = document.getElementById("myChart");
this.chart = new Chart(ctx, {
type: "line",
data: {
labels: [],
datasets: [],
},
});
},
data() {
return {
selected: "",
chart: null,
options: [
{ text: "msft", value: "msft" },
{ text: "GOOGL", value: "GOOGL" },
],
};
},
watch: {
selected: function () {
this.getPrice();
},
},
methods: {
async getPrice() {
let { data } = await axios.get("https://site/....");
this.chart.data.datasets = [{ label: "dummy data" , data: [2, 3, 4]}];
this.chart.data.label = [1, 2, 3];
this.chart.update(); //very important, always update it
},
},
};
</script>
You create a property called chart and save your chart to it.
Then, after you fetch your data, you can access your chart with this.chart and then you set your datasets and labels. Whenever you make an change to the chart, use this.chart.update() to update it on the browser.
If you execute this code, you should see some dummy data in the chart

Vue Cant render data from axios inside datatable

i am trying to get data from axios and then render it in datable component
how you can see the hardcoded data is renderd every time , but i cant implement data from axios call,
i am loading same format data from axios and then try to update my hardocded rows but nothing happens, i am not shure thath i am doing it right way
can somone help
<template>
<div>
<mdb-datatable-2 v-model="data" />
</div>
</template>
<script>
import { mdbDatatable2 } from 'mdbvue';
export default {
name: 'Datatable',
components: {
mdbDatatable2
},
data() {
return {
data: {
columns: [
{
label: 'Account',
field: 'account',
sort: true
},
{
label: 'bt_mac',
field: 'bt_mac',
sort: true
},
{
label: 'rssi',
field: 'rssi',
sort: true
},
{
label: 'time_stamp',
field: 'time_stamp',
sort: true
}
],
rows: [{
account: 'Tiger Nixon',
bt_mac: 'System Architect',
rssi: 'Edinburgh',
time_stamp: '2011/04/25',
time: '2011/04/25'
},
{
account: 'Garrett Winters',
bt_mac: 'Accountant',
rssi: 'Tokyo',
time_stamp: '2018/04/25',
time: '2011/04/25'
},
{
account: 'Ashton Cox',
bt_mac: 'unior Technical Author',
rssi: 'San Francisco',
time_stamp: '2009/01/12',
time: '2011/04/25'
},]
}
}
},
methods: {
getSnomData () {
this.axios.get('http://172.27.11.174:1818/testJson').then((response) => {
console.log(this.data);
console.log(response.data.rows); this.rows = response.data;
console.log(this.data);
return response;
})
}
},
created() {
this.getSnomData();
}
,
mounted () {
this.getSnomData();
}
}
</script>
this.data.rows = response.data.data;
that helped in my case

Vue.js dynamic component render "Failed to resolve directive"

Currently I have solved things in an other way, but I am still curious why this is not working.
I'm trying to render a transition with a template with 2 directives, but it seems it tries to resolve the attrs/props from an other scope, but I can't see why at this point. Perhaps I just made a stupid mistake.
This gives me the error:
"[Vue warn]: Failed to resolve directive: ..." for both bind and text
<script>
import Step from './Step';
export default {
data() {
return {
pointer: 0,
steps: [],
}
},
render(createElement) {
this.steps = this.$slots.default
.filter(vnode => vnode.tag && vnode.tag.indexOf(Step.name) > -1);
this.pointer = this.steps[0].key;
return createElement('div',
{},
[
createElement('transition',
{},
[
createElement('template', {
directives: [
{name: 'bind', arg: 'key', value: 'pointer'},
{name: 'text', value: 'step'},
],
})
]
)
]);
},
computed: {
step() {
return _.find(this.steps, step => step.key === this.pointer);
}
},
methods: {
next() {
++this.pointer;
}
}
}
</script>