In Vue how do I replace array with new array? - vue.js

Every 10 seconds I query my database for latest fire calls. I do app.events = data.calls but my data doesn't refresh. I initialize the data with the same function that is called every 10 seconds. I see the table. How I do I replace an array in Vue with an array?
<html>
<head>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script src="https://unpkg.com/vue"></script>
<script>
$(function() {
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
$('#demo').text("Geolocation is not supported by this browser.");
}
}
function showPosition(position) {
$.get('http://localhost:8000/api/nearest_events?lng='+position.coords.longitude+'&lat='+position.coords.latitude, function(data) {
//app.$set(app.events, Object.assign({}, app.events, data.calls));
app.events = data.calls;
})
}
app = new Vue({
el: '#app',
data: {
events: []
},
created: function() {
setInterval(getLocation(), 10000)
}
})
})
</script>
<style>
td, th {border:1px solid #000;padding:5px}
table { border-collapse:collapse;}
</style>
</head>
<body>
<div id="app">
<table>
<tr v-for="event in events">
<td>{{ event.datetime }}</td>
<td>{{ event.address }}</td>
<td>{{ event.type }}</td>
<td>
<table>
<tr><th>Unit</th><th>Dispatched at</th><th>Arrived at</th><th>In service</th></tr>
<tr v-for="unit in event.units">
<td>{{ unit.unit }}</td>
<td>{{ unit.dispatched }}</td>
<td>{{ unit.arrived }}</td>
<td>{{ unit.in_service }}</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</body>
</html>

It appears that your problem is in setInterval. When you call getLocation it does not require the ()
i = 0;
app = new Vue({
el: '#app',
data: {
events: []
},
methods: {
getLocation: function () {
var self = this;
i+=1;
self.events = [1,2,3,i];
}
},
created: function() {
self = this;
setInterval(self.getLocation, 1000);
}
})
And here is a working demo:
https://codepen.io/egerrard/pen/EwLVNB

Related

Cannot iterate the data from an array ref VUEJS

I'm having a slight issue here when i try to iterate through the data array from "history" ref
As we see here, there is 2 console log, 1 from the request and 1 after we put the data in history both show 2 array which is what the values should be but there is nothing on the table and yes every row have an unique id in the database
I'm still pretty new to vuejs ^^
Template
<template>
<div class="container">
<h3 v-if="loading"> Loading... </h3>
<table>
<tr>
<th>Title</th>
<th>Shares</th>
<th>Price</th>
</tr>
<tr ref="history" v-for="row in history" :key="row.id" >
<td>{{ row.title }}</td>
<td>{{ row.shares }}</td>
<td>{{ row.price }}</td>
</tr>
</table>
</div>
Script
<script>
import { store } from "../store"
import { onMounted, ref, reactive } from "vue"
import { supabase } from "#/supabase"
export default {
setup () {
const loading = ref(true);
const user = supabase.auth.user();
const history = ref([])
async function getHistory() {
try {
loading.value = true;
let { data, error, status } = await supabase
.from("history")
.select(`id, user_id, title, shares, price`)
.eq("user_id", user.id)
console.log(data)
if (error && status !== 406) throw error
if (data) {
history.value = data
console.log(history.value)
}
} catch (error) {
alert(error.message)
} finally {
loading.value = false
}
}
onMounted(() => {
getHistory()
})
return {
loading,
user,
history,
}
},
data() {
return {}
}
}
The issue is using ref="history" on the tr tag, as it will bind the ref with the DOM element, you need to remove it.
<tr v-for="row in history" :key="row.id" >
<td>{{ row.title }}</td>
<td>{{ row.shares }}</td>
<td>{{ row.price }}</td>
</tr>

Vue.js Displaying data from websocket into a table and sending data to other component

Version: Vue CLI 2.6.x
I am trying to resolve two issues:
Issue 1:
My Vue app has subscribed to updates via a websocket. I am getting the data continuously and need to keep the table updated with the received data. However the table remains empty even when the list (aqiDataList) has content in it.
Issue 2:
I also need to pass the aqiDataList to the AQITableComponent (where the actual table was originally suppose to be) but having this same issue
App.vue
<template>
<v-container>
<AQITableComponent :aqiList="aqiDataList" />
<v-simple-table>
<template v-slot:default>
<thead>
<tr>
<th class="text-left">
Name
</th>
<th class="text-left">
Age
</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr
v-for="item in aqiDataList"
:key="item.id"
>
<td>{{ item.name }}</td>
<td>{{ item.age }}</td>
<td>{{ item.location }}</td>
</tr>
</tbody>
</template>
</v-simple-table>
</v-container>
</template>
<script>
import AQITableComponent from './AQITableComponent';
export default {
name: 'AQIComponent',
components: {
AQITableComponent
},
data: function () {
return {
connection: null,
aqiDataList: []
};
},
mounted() {
},
methods: {
},
created: function () {
console.log("Starting connection to WebSocket Server");
this.connection = new WebSocket("wss://my-websocket.com");
this.connection.onmessage = function (event) {
//console.log(event.data);
let aqiDataString = event.data;
this.aqiDataList = [];
let parsedData = JSON.parse(aqiDataString);
parsedData.forEach((aqiData) => {
this.aqiDataList.push({
... object
});
});
console.log(this.aqiDataList);
};
this.connection.onopen = function (event) {
console.log(event);
console.log("Successfully connected to the echo websocket server...");
};
},
}
</script>
AQITableComponent.vue
<template>
<v-container>
<v-simple-table>
<template v-slot:default>
.. same table as shown above
</template>
</v-simple-table>
</v-container>
</template>
<script>
export default {
name: 'AQITableComponent',
props: ['aqiList'],
data: function () {
},
}
</script>
(1) Try using the arrow function for the onmessage event:
from: this.connection.onmessage = function (event) {...}
to: this.connection.onmessage = (event) => {...}
or: this.connection.addEventListener("message", (event) => {...});
This way the this.aqiDataList will be available on your component. Inside the event callback.
This should also solve the problem (2) since your array is not being updated on the first place.

Load More Data On Scroll With Vue And Vuex

I would like to ask how can I display more data by using Vue and vuex. all data stored in vuex-store management already. From State management now I want to load more data on scrolling.
I found online solution by ajax. but I need to loading form state management (Vuex).
This is my Vue template:
<template>
<div>
<div class="panel panel-default">
<div class="panel-body">
<table class="table table-bordered table-striped">
<thead>
<tr>
<tr>
<th>Name - Number of Products: <span style="color: red"> {{products}} </span></th>
<th width="100"> </th>
</tr>
</tr>
</thead>
<tbody v-if="isLoaded">
<tr v-for="company, index in companies">
<td>{{ company.name }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script>
export default {
data: function () {
return { }
},
computed: {
companies(){
return this.$store.getters['exa1Company/getProducts'];
},
products(){
return this.$store.getters['exa1Company/countProducts'];
}
},
mounted() {
this.$store.dispatch('exa1Company/indexResource');
}
}
</script>
My vuex store file is partial for simplicity
export const getters = {
countProducts(state) {
return state.list.data.length;
},
getProducts(state) {
return state.list.data;
},
getTodoById: (state) => (id) => {
return state.list.data.find(tod => tod.id === id)
}
};
export default {
namespaced: true,
state: customerState,
getters,
actions,
mutations,
};
something like this should work. use companiesLoaded in the template, and increase page when scrolled to bottom. I hope this helps.
data: function () {
return {
page: 1,
perPage: 20
}
},
computed: {
companies(){
return this.$store.getters['exa1Company/getProducts'];
},
companiesLoaded(){
return this.companies.slice(0, this.page * this.perPage)
},
...

Vue get id from table row

How will I get selected item in this table row. I want When I click on the row its gives me the cowId then I can use it . is there a way i can do this in a very simple way without much modification. then i can send thecowwid to my api via axios for deleting
<div id="ArtificialInsemination" class="container">
<button v-on:click="viewRecords">View Record</button>
<table class="table table-striped">
<thead>
<tr>
<th>Cow Id</th>
<th>Bull Name</th>
<th>Semen Origin</th>
<th>Insemination Time</th>
<th>Pd Delivery Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for ="artificialInseminationRecord in artificialInseminationRecords">
<td>{{ artificialInseminationRecord.cowId }}</td>
<td>{{ artificialInseminationRecord.bullUsedName }}</td>
<td>{{ artificialInseminationRecord.semenOrigin }}</td>
<td>{{ artificialInseminationRecord.inseminationTime }}</td>
<td>{{ artificialInseminationRecord.pdStatusDate }}</td>
<td><button v-on:click="DeleteArtificialInseminationRecords" >Delete</button></td>
</tr>
</tbody>
</table>
</div>
this VUE to GET COW ID WHEN a row in a table clicked
<script>
//class initialization
var ArtificialInsemination = new Vue({
el:'#ArtificialInsemination',
data: {
url:'http://localhost/dairyfarm/index.php',
artificialInseminationRecords: [],
cowId: ''
},
//invoke methods
methods: {
viewRecords:function () {
var data = new FormData()
data.append('function','viewRecords')
axios.post(this.url,data)
.then( function (response ) {
this.artificialInseminationRecords = response.data.data
}.bind(this)).catch(function (error) {
})
}, saveInseminationRecords:function () {
var data = new FormData()
data.append('function','saveInseminationRecords')
axios.post(this.url,data)
.then( function (response ) {
this.artificialInseminationRecords = response.data.data
}.bind(this)).catch(function (error) {
})
}, DeleteArtificialInseminationRecords:function () {
this.cowId = 'GET COW ID HERE'
var data = new FormData()
data.append('function','DeleteArtificialInseminationRecords')
data.append('cowId',this.cowId)
axios.post(this.url,data)
.then( function (response ) {
}.bind(this)).catch(function (error) {
})
},
create: function(){
this.viewRecords()
}.bind(this),
}
})
</script>
Complete example. Hope it helps.
const store = new Vuex.Store({
state: {
users: null
},
mutations: {
updateUsers (state, payload) {
state.users = payload
}
},
actions: {
async loadUsers ({commit}, payload) {
var response = await axios.get(payload.src)
commit('updateUsers', response.data )
}
}
})
Vue.component('user-list', {
template: '#user-list',
props: ['src'],
methods: {
removeUser (id) {
alert('You are deleting user id: ' + id)
// axios.delete('https://your.rest.api/users/' + id)
}
},
created () {
this.$store.dispatch('loadUsers', {src: this.src})
}
})
new Vue({
el: '#app',
store
})
table {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
border: 1px solid black;
padding: 3px;
}
td:last-child {
text-align: center;
}
<div id="app">
<user-list src="https://jsonplaceholder.typicode.com/users">
</user-list>
</div>
<template id="user-list">
<table>
<thead>
<tr>
<th>ID</th>
<th>Nick</th>
<th>Full name</th>
<th>Actions</th>
</tr>
</thead>
<tr v-for="user in $store.state.users" :key="user.id">
<td>{{ user.id }}</td>
<td>{{ user.username }}</td>
<td>{{ user.name }}</td>
<td><button #click="removeUser(user.id)">X</button></td>
<tr>
</table>
</template>
<script src="https://unpkg.com/vue#2.5.2/dist/vue.min.js"></script>
<script src="https://unpkg.com/vuex#3.0.0/dist/vuex.min.js"></script>
<script src="https://unpkg.com/axios#0.17.0/dist/axios.min.js"></script>

Vue data referencing issue

This is strange because it was just working last night, but basically I have a Vue app that's pulling JSON from my backend. Code below. The strange part is that while the loadData function is running and I see the 'Loaded Data' message in console along with the list of items from the JSON, I then get a console error saying 'items is not defined'. I must have made a subtle typo or some dumb change but I can't find it anywhere!! Any ideas?
HTML snippet:
<div id="app">
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Query</th>
<th>Initiated By</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<div v-for="item in items">
<td>{{ item.id }}</td>
<td>{{ item.query }}</td>
<td>{{ item.user }}</td>
<td>{{ item.type }}</td>
</div>
</tr>
</tbody>
</table>
</div>
</div>
(And then <script src="app.js"></script> right before </body>)
JS code:
new Vue({
el: '#app',
data: {
items: [],
interval: null
},
methods: {
loadData: function () {
$.get('http://localhost:4567/getQueue', function (response) {
this.items = response.results;
console.log("Loaded data.")
console.log(response.results)
}.bind(this));
}
},
created: function () {
console.log("Loading data...")
this.loadData();
console.log(items)
this.interval = setInterval(function () {
this.loadData();
}.bind(this), 3000);
},
beforeDestroy: function(){
clearInterval(this.interval);
}
});
You are getting the error
items is not defined
because of following line:
created: function () {
console.log("Loading data...")
this.loadData();
console.log(items) <== this should be console.log(this.items)
Turns out there was a few issues in my code.
1) As was pointed out by Saurabh, I forgot to put this.items instead of items.
2) this can't be referenced inside of the function I defined as I have it... instead, the function has to be defined with =>, for example:
$.get('http://localhost:4567/getQueue').then((response) => {
this.items = response.data.results;
console.log("loadData finished - items length is: "+this.items.length)
})
3) The big error I had was that my div bind with items was inside the table tag, which apparently isn't okay to do. Instead I applied the Vue binds to the existing tags (table, tr).