Vue: Getting a time in a seconds on page mount and creating hh:mm:ss off of that? - vue.js

I am getting a getSecondsUptime field when a component mounts, saving it to initialData and then want to increment that each second. However, I am getting an infinite loop warning and hundreds of console logs within seconds. I can't tell what I am doing wrong.
data() {
return {
time: 0,
}
},
mounted() {
this.time = this.$store.getters['into/getSecondsUptime'];
setInterval(this.calcTime, 1000)
},
methods: {
calcTime: function() {
console.log('foo');
this.time = this.time + 1;
let date = new Date(null);
date.setSeconds(this.time);
let result = date.toISOString().substr(11, 8);
return result;
}
}

you are calling your calcTime function multiple times. Maybe you can change to like this
mounted() {
this.time = this.$store.getters['into/getSecondsUptime'];
this.calcTime()
},
methods: {
calcTime: function() {
setInterval(() => {
this.time = this.time + 1
}, 1000);
}
}

You can call calcTime by Using window.setInterval which will be called every second. Like below
mounted() :{
this.time = this.$store.getters['into/getSecondsUptime'];
window.setInterval(() => {
this.calcTime();
}, 1000);
},
methods: {
calcTime() {
console.log('foo');
this.time = this.time + 1;
let date = new Date(null);
date.setSeconds(this.time);
let result = date.toISOString().substr(11, 8);
return result;
}
}

Related

Highcharts with decrease order in each interval

Is it possible to create a graph sorted in each time interval using Highcharts?
For expample, in this picture for January data will be in order: New York, Tokyo, London, Berlin. The same for each months - data should be shown decrease order
Highcharts doesn't have a built-in function to do that, but for example you can use the render event and organize columns, by changing their positions in the way you need.
events: {
render: function() {
var series = this.series,
longestSeries = series[0],
sortedPoints = [],
selectedPoints = [];
// find a series with the highest amount of points
series.forEach(function(s) {
if (s.points.length > longestSeries.points.length) {
longestSeries = s;
}
});
longestSeries.points.forEach(function(point) {
series.forEach(function(s) {
selectedPoints.push(s.points[point.index]);
});
sortedPoints = selectedPoints.slice().sort(function(a, b) {
return b.y - a.y;
});
selectedPoints.forEach(function(selectedPoint) {
if (
selectedPoints.indexOf(selectedPoint) !==
sortedPoints.indexOf(selectedPoint) &&
selectedPoint.graphic
) {
// change column position
selectedPoint.graphic.attr({
x: sortedPoints[selectedPoints.indexOf(selectedPoint)].shapeArgs.x
});
}
});
sortedPoints.length = 0;
selectedPoints.length = 0;
});
}
}
Live demo: https://jsfiddle.net/BlackLabel/tnrch8v1/
API Reference:
https://api.highcharts.com/highcharts/chart.events.render
https://api.highcharts.com/class-reference/Highcharts.SVGElement#attr
#ppotaczek Thank You for help a lot! I solve my issue, but i had to make some changes to your code:
events: {
render: function() {
if (this.series.length === 0) return
var series = this.series,
longestSeries = series[0],
sortedPoints = [],
selectedPoints = [];
// find a series with the highest amount of points
series.forEach(function(s) {
if (s.points.length > longestSeries.points.length) {
longestSeries = s;
}
});
longestSeries.points.forEach(function(point) {
series.forEach(function(s) {
selectedPoints.push(s.points[point.index]);
});
sortedPoints = selectedPoints.slice().sort(function(a, b) {
return b.y - a.y;
});
selectedPoints.forEach(function(selectedPoint) {
if (
selectedPoints.indexOf(selectedPoint) !==
sortedPoints.indexOf(selectedPoint) &&
selectedPoint.graphic
) {
// change column position
selectedPoint.graphic.attr({
x: selectedPoints[sortedPoints.indexOf(selectedPoint)].shapeArgs.x
});
}
});
sortedPoints.length = 0;
selectedPoints.length = 0;
});
}
},
}
So i changed:
// change column position
selectedPoint.graphic.attr({
x: sortedPoints[selectedPoints.indexOf(selectedPoint)].shapeArgs.x
});
to:
// change column position
selectedPoint.graphic.attr({
x: selectedPoints[sortedPoints.indexOf(selectedPoint)].shapeArgs.x
});

Can't pass my data to the mounted() method

I am fairly new to Vue so excuse my stupidity!!
Can anyone tell me what I am doing wrong in my code below that is preventing me from getting my 'series_interactions_daily' variable data from inside the mounted() method please? I am console.log()'ing it but nothing shows! I can print 'series_interactions_daily' to screen in the HTML though!
<script>
import * as am4core from "#amcharts/amcharts4/core";
import * as am4charts from "#amcharts/amcharts4/charts";
import am4themes_animated from "#amcharts/amcharts4/themes/animated";
am4core.useTheme(am4themes_animated);
export default {
mounted() {
let chart = am4core.create(this.$refs.chartdiv, am4charts.XYChart);
chart.paddingRight = 20;
let dummydata = [];
let visits = 10;
for (let i = 1; i < 366; i++) {
visits += Math.round((Math.random() < 0.5 ? 1 : -1) * Math.random() * 10);
dummydata.push({ date: new Date(2018, 0, i), name: "name" + i, value: visits });
}
chart.data = dummydata;
console.log(this.series_interactions_daily);
let dateAxis = chart.xAxes.push(new am4charts.DateAxis());
dateAxis.renderer.grid.template.location = 0;
let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.tooltip.disabled = true;
valueAxis.renderer.minWidth = 35;
let series = chart.series.push(new am4charts.LineSeries());
series.dataFields.dateX = "date";
series.dataFields.valueY = "value";
series.tooltipText = "{valueY.value}";
chart.cursor = new am4charts.XYCursor();
let scrollbarX = new am4charts.XYChartScrollbar();
scrollbarX.series.push(series);
chart.scrollbarX = scrollbarX;
this.chart = chart;
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose();
}
},
data() {
return {
campaign_id: this.$route.params.campaign_id,
campaign: [],
dateranges: [],
total_interactions: '',
average_daily_interactions: '',
series_interactions_daily: [],
}
},
methods: {
onChange(event) {
this.$router.push('?range=' + event.target.value);
this.$http.get('https://dev.local/api/portal/campaign/' + this.campaign_id + '?range=' + event.target.value)
.then(function(data){
return data.json();
}).then(function(data){
this.campaign = data.campaign;
this.dateranges = data.dateranges;
this.total_interactions = data.totalInteractions;
this.average_daily_interactions = data.averagreDailyInteractions;
this.series_interactions_daily = data.interactions_per_day.stats.interaction.daily;
});
}
},
created() {
this.$http.get('https://dev.local/api/portal/campaign/' + this.campaign_id + '?' + this.axiosParams)
.then(function(data){
return data.json();
}).then(function(data){
this.campaign = data.campaign;
this.dateranges = data.dateranges;
this.total_interactions = data.totalInteractions;
this.average_daily_interactions = data.averagreDailyInteractions;
this.series_interactions_daily = data.interactions_per_day.stats.interaction.daily;
});
},
computed: {
axiosParams() {
const params = new URLSearchParams();
if(this.$route.query.range) params.append('range', this.$route.query.range);
return params;
}
},
filters: {
},
directives: {
},
}
</script>
EDIT
OK, so I have create a method to fetchData() from mounted(){} - however I am still not getting my 'series_interactions_daily' variable data!
<script>
import * as am4core from "#amcharts/amcharts4/core";
import * as am4charts from "#amcharts/amcharts4/charts";
import am4themes_animated from "#amcharts/amcharts4/themes/animated";
am4core.useTheme(am4themes_animated);
export default {
mounted() {
this.fetchData();
let chart = am4core.create(this.$refs.chartdiv, am4charts.XYChart);
chart.paddingRight = 20;
let dummydata = [];
let visits = 10;
for (let i = 1; i < 366; i++) {
visits += Math.round((Math.random() < 0.5 ? 1 : -1) * Math.random() * 10);
dummydata.push({ date: new Date(2018, 0, i), name: "name" + i, value: visits });
}
chart.data = dummydata;
console.log(this.series_interactions_daily);
let dateAxis = chart.xAxes.push(new am4charts.DateAxis());
dateAxis.renderer.grid.template.location = 0;
let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.tooltip.disabled = true;
valueAxis.renderer.minWidth = 35;
let series = chart.series.push(new am4charts.LineSeries());
series.dataFields.dateX = "date";
series.dataFields.valueY = "value";
series.tooltipText = "{valueY.value}";
chart.cursor = new am4charts.XYCursor();
let scrollbarX = new am4charts.XYChartScrollbar();
scrollbarX.series.push(series);
chart.scrollbarX = scrollbarX;
this.chart = chart;
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose();
}
},
data() {
return {
campaign_id: this.$route.params.campaign_id,
campaign: [],
dateranges: [],
total_interactions: '',
average_daily_interactions: '',
series_interactions_daily: [],
}
},
methods: {
fetchData() {
this.$http.get('https://dev.local/api/portal/campaign/' + this.campaign_id + '?' + this.axiosParams)
.then(function(data){
return data.json();
}).then(function(data){
this.campaign = data.campaign;
this.dateranges = data.dateranges;
this.total_interactions = data.totalInteractions;
this.average_daily_interactions = data.averagreDailyInteractions;
this.series_interactions_daily = data.interactions_per_day.stats.interaction.daily;
});
},
onChange(event) {
this.$router.push('?range=' + event.target.value);
this.$http.get('https://connie.laravel/api/portal/campaign/' + this.campaign_id + '?range=' + event.target.value)
.then(function(data){
return data.json();
}).then(function(data){
this.campaign = data.campaign;
this.dateranges = data.dateranges;
this.total_interactions = data.totalInteractions;
this.average_daily_interactions = data.averagreDailyInteractions;
this.series_interactions_daily = data.interactions_per_day.stats.interaction.daily;
});
}
},
created() {
},
computed: {
axiosParams() {
const params = new URLSearchParams();
if(this.$route.query.range) params.append('range', this.$route.query.range);
return params;
}
},
filters: {
},
directives: {
},
}
</script>
Any help appreciated.
Thanks,
K...
In fetchData, return the promise returned by the async $http call:
fetchData() {
return this.$http.get(...)
...
}
Now you can register a callback on that promise in mounted:
mounted() {
this.fetchData().then(result => {
...
});
}
Or just await it with async/await:
async mounted() {
await this.fetchData();
...
// Now everything will be ready
}
As #tao mentioned in comments, note that the await would delay any code that comes after it. If you don't have anything else to do in the hook anyway that's no problem but it's something to understand.

ESLint Expected to return a value at the end of method

i have this code
computed: {
termOptions() {
if (this.newSchedule.originCharges.serviceType !== 'If Any') {
return this.serviceOptions.filter((val) => val.name !== 'If Any');
}
},
isMoreThanToday() {
if (this.newSchedule.validFrom) {
const date = new Date();
const isMore = this.newSchedule.validFrom < date.getDate();
return isMore;
}
},
}
and i got an error saying expected return value at the of method. Is there any way to fix this? thank you.
This is ESLint error. It tells you that a computed property should always return some value.
Your computed properties return values only when the condition of the if is true and don't return anything when it's false.
computed: {
termOptions() {
if (this.newSchedule.originCharges.serviceType !== 'If Any') {
return this.serviceOptions.filter((val) => val.name !== 'If Any');
}
else {
return []
}
},
isMoreThanToday() {
if (this.newSchedule.validFrom) {
const date = new Date();
const isMore = this.newSchedule.validFrom < date.getDate();
return isMore;
}
else {
return false
}
},
}
See this page for details.

setInterval doesn't fire in vue

im learning vue and setInterval doesn't work like in normal javascript? the problem is that my update function doesn't get fired.
start gets fired from a button, and hours/minutes/seconds are bound to input fields with v-model, i get all console.logs before the setInterval.
export default Vue.extend({
name: "timer-c",
data() {
return {
startDate: undefined,
hours: "",
minutes: "",
seconds: "",
timeLeft: undefined,
endDate: undefined,
interval: undefined,
text: "00:00:00",
sub: undefined,
};
},
methods: {
start: function() {
if (this.sub === undefined) {
let sum = 0;
if (this.seconds.match(/^\d+$/)) {
sum = sum + this.seconds * 1000;
console.log(sum);
}
if (this.minutes.match(/^\d+$/)) {
sum = sum + this.minutes * 60 * 1000;
}
if (this.hours.match(/^\d+$/)) {
sum = sum + this.hours * 60 * 60 * 1000;
}
if (sum === 0) {
console.log(this.$refs.br_start);
this.failed = true;
} else {
console.log(sum);
this.failed = false;
this.endDate = new Date(Date.now() + sum);
console.log(this.endDate);
this.startDate = new Date(Date.now());
console.log(this.startDate);
this.interval = setInterval(time => this.update, 1000);
//this.sub = this.interval.subscribe(time => this.update(time));
}
}
},
update: function() {
console.log('test');
const timeRemaining = Math.round((Date.now() - this.endDate) / 1000);
this.text = timeRemaining;
if (new Date(Date.now()) >= this.endDate) {
console.log("test");
}
},
Try to not return the function but execute it
this.interval = setInterval(time => { this.update(time) }, 1000);

Vue.js - Input, v-model and computed property

I'm using vue-2.4 and element-ui 1.4.1.
Situation
I have a basic input which is linked with v-model to a computed property. When blur I check if the value input is greater or lower than min and max and I do what I have to do ... Nothing fancy here.
Problem
The value displayed in the input does not always equal enteredValue
Steps to reproduce
1) Input 60 --> Value displayed is the max so 50 and enteredValue is 50 (which is ok)
2) Click outside
3) Input 80 --> Value displayed is 80 and enteredValue is 50
Questions
How can I fix that so the value displayed is always the same as the enteredValue ?
Here is the minimal code to reproduce what I'm facing JSFIDDLE
<div id="app">
The variable enteredValue is {{enteredValue}}
<el-input v-model="measurementValueDisplay" #blur="formatInput($event)"></el-input>
</div>
var Main = {
data() {
return {
enteredValue: '',
max: 50,
min: 10
}
},
computed: {
measurementValueDisplay: {
get: function () {
return this.enteredValue + ' inchs'
},
set: function (newValue) {
}
},
},
methods: {
formatInput($event) {
let inputValue = $event.currentTarget.value;
if (inputValue > this.max) { this.enteredValue = this.max}
else if (inputValue < this.min) { this.enteredValue = this.min}
else this.enteredValue = inputValue
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
Reading this vuejs, will understand what happens
"computed properties are cached based on their dependencies. A computed property will only re-evaluate when some of its dependencies have changed."
Changed some comportament of the code. Made run:
computed() method not works properly for update value in window. But if looks at console the value yes updated.
So, i remove computed (getter and setter), and put into data, without setter and getter( i dont like this in javascript).
var Main = {
data() {
return {
measurementValueDisplay:'fff',
enteredValue: '',
max: 50,
min: 10
}
},
computed: {
/*measurementValueDisplay: {
get: function () {
console.log('Computed was triggered so I assume enteredValue changed',this.enteredValue);
return this.enteredValue + ' inchs'
},
set: function (newValue) {
console.log('setter de qye', this.enteredValue);
}
},*/
},
methods: {
formatInput($event) {
this.enteredValue = 0;
let inputValue = $event.currentTarget.value;
console.log(inputValue);
if (inputValue > this.max) { this.enteredValue = this.max}
else if (inputValue < this.min) { this.enteredValue = this.min}
else this.enteredValue = inputValue
this.measurementValueDisplay = this.enteredValue + ' inchs'
console.log(this.enteredValue, 'oioioioio0');
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
Your problem is that the values used in the computed property was not updated with the validation capping at 50 (Was 50, is now updated to 50, no need to recalculate), therefore v-model did not update the input.
I've edited your jsfiddle to use two computed properties:
One with an accessor to validate the entered value, one which returns the value with " inch" appended.
Here is the interesting part:
computed: {
measurementValueDisplay: {
get: function () {
return this.enteredValue
},
set: function (newValue) {
this.enteredValue = 0;
let inputValue = parseInt(newValue);
if(Number.isNaN(inputValue)){this.enteredValue = this.min}
else if (inputValue > this.max) { this.enteredValue = this.max}
else if (inputValue < this.min) { this.enteredValue = this.min}
else this.enteredValue = inputValue
}
},
valueWithInch(){
return this.enteredValue + " inch";
}
},
In case anybody still needs a hack for this one, you can use a value that will always change ( for example a timestamp )
var Main = {
data() {
return {
enteredValue: '',
max: 50,
min: 10,
now: 1 //line added
}
},
computed: {
measurementValueDisplay: {
get: function () {
return (this.now - this.now + 1 ) * this.enteredValue + ' inchs'; //line changed
},
set: function (newValue) {
this.now = Date.now(); //line added
}
},
},
methods: {
formatInput($event) {
let inputValue = $event.currentTarget.value;
if (inputValue > this.max) { this.enteredValue = this.max}
else if (inputValue < this.min) { this.enteredValue = this.min}
else this.enteredValue = inputValue
}
}
}