ionic 2 - Using Highchart in the Segment - ionic2

I use HighChart library in the Segment, my segment have 2 tab DASHBOARD and NEW, my Chart in the DASHBOARD tab. First run: My Chart run, but i click to New tab and come back DASHBOARD tab => My chart not run ?
[sorry, i'm not good english]
-- My code html:
<div class="segment-chart">
<ion-segment [(ngModel)]="pet">
<ion-segment-button value="dashboard" (ionSelect)="selectedFriends()">
DASHBOARD
</ion-segment-button>
<ion-segment-button value="new">
NEW
</ion-segment-button>
</ion-segment>
</div>
<div [ngSwitch]="pet">
<div class="chart" *ngSwitchCase="'dashboard'">
<!--View Chart-->
<div #chart>
<chart type="StockChart" [options]="options"></chart>
</div>
</div>
<ul *ngSwitchCase="'new'" style="list-style-type:none" class="div-new-body">
<li class="div-new-li" *ngFor="let new of lsNews">
<div class="div-new-detail">
<div class="div-new-title">
{{new.date}}
</div>
<div class="div-new-content">
{{new.title}}
</div>
</div>
<div class="div-new-nav">></div>
</li>
</ul>
</div>
My code file ts:
export class ChartPage implements AfterViewInit, OnDestroy {
private _chart: any;
lastData: any
lstData: any = []
pet : any
lsNews : any = []
opts : any;
#ViewChild('chart') public chartEl: ElementRef;
//chartOption: any
// Destroy Chart
ngOnDestroy(): void {
// throw new Error("Method not implemented.");
console.log("OnDestroy run")
var chart = this._chart
chart.destroy();
}
// option Chart
ngAfterViewInit() {
if (this.chartEl && this.chartEl.nativeElement) {
this.opts.chart = {
// type: 'area',
renderTo: this.chartEl.nativeElement,
backgroundColor: {
linearGradient: [0, 0, 500, 500],
stops: [
[0, '#3d4d64'],
[1, '#3d4d64']
]
},
height: '90%',
spacingBottom: 15,
spacingTop: 10,
spacingLeft: 10,
spacingRight: 10,
};
console.log('chart create ss')
this._chart = new Highcharts.StockChart(this.opts);
}
}
constructor(public navCtrl: NavController, public navParams: NavParams, public service: Service) {
const me = this;
this.pet= 'dashboard';
setInterval(function () {
if (me._chart) {
me._chart['series'][0].addPoint([
(new Date()).getTime(), // gia tri truc x
//5// gia tri truc y
me.getData()
],
true,
true);
}
}, 3000);
this.opts = {
credits: {
enabled: false
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150,
labels: {
style: {
color: '#705f43' // color time
}
},
lineColor: '#705f43' // 2 line cuoi mau trang
},
yAxis: {
gridLineColor: '#705f43', //line gach ngang
labels: {
style: {
color: '#fff'
}
},
lineColor: '#ff0000',
minorGridLineColor: '#ff0000',
tickColor: '#fff',
tickWidth: 1,
title: {
style: {
color: '#ff0000'
}
}
},
navigator: {
enabled: false
},
rangeSelector: {
buttons: [{
count: 1,
type: 'minute',
text: '1M'
}, {
count: 5,
type: 'minute',
text: '5M'
}, {
type: 'all',
text: 'All'
}],
inputEnabled: false,
selected: 0,
},
series: [{
name: 'Random data',
data: (function () {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -50; i <= 0; i += 1) {
data.push([
time + i * 1000,
Math.round(Math.random() * 100)
]);
}
return data;
}()),
zones: [{
color: '#f8ad40'
}]
}]
};
//end contructor
}

In case you have not been able to resolve this issue, I had the same issue using ion-segment and I was able to resolve it when I replaced ngSwitch with the [hidden] property.
The problem is that the canvas only get rendered once. The canvas is also lost once you switch between your segments, the only solution is to hide you segment when switching between segments
Edit your HTML code to the one below and you should be okay
<div class="segment-chart">
<ion-segment [(ngModel)]="pet">
<ion-segment-button value="dashboard" (ionSelect)="selectedFriends()">
DASHBOARD
</ion-segment-button>
<ion-segment-button value="new">
NEW
</ion-segment-button>
</ion-segment>
</div>
<div >
<div class="chart" [hidden] = "pet != 'dashboard'">
<!--View Chart-->
<div #chart>
<chart type="StockChart" [options]="options"></chart>
</div>
</div>
<ul [hidden] = "pet != 'new'" style="list-style-type:none" class="div-new-body">
<li class="div-new-li" *ngFor="let new of lsNews">
<div class="div-new-detail">
<div class="div-new-title">
{{new.date}}
</div>
<div class="div-new-content">
{{new.title}}
</div>
</div>
<div class="div-new-nav">></div>
</li>
</ul>
</div>
That should solve the issue.

Related

why do other charts on my webpage are not showing eventho there is no syntax error in PhP and charts.js?

I made a dashboard on my website that has 3 different visualization charts, the data is from my database, and the problem that I'm encountering is that the other two are not showing eventhough the first one shows itself. moreover, if I hide or remove the first chart, the second one appears, but the third one still doesn't show. refer to images below:
First Chart Shows the following two are not.
The second chart only shows itself when I delete the code of the first chart.
The 3rd chart is the same case as 2nd, needed to remove the first and second charts just to see the third one.
here is my code:
<!--CHARTS-->
<!--BAR CHART-->
<div class="container-fluid px-4">
<?php
// Attempt select query execution
try{
$barsql = "SELECT * FROM castro_rentals.unit";
$barresult = $pdo->query($barsql);
if($barresult->rowCount() > 0) {
$price = array();
$unit_no = array();
while($row = $barresult->fetch()) {
$price[] = $row["price"];
$unit_no[] = $row["unit_no"];
}
unset($barresult);
} else {
echo "No records matching your query were found.";
}
} catch(PDOException $e){
die("ERROR: Could not able to execute $barsql. " . $e->getMessage());
}
// Close connection
unset($pdo);
?>
<div class="card mb-4">
<!--BAR CHART-->
<div class="card-header">
<i class="fas fa-chart-bar me-1"></i>
Unit Prices
</div>
<div class="card-body">
<canvas id="myBarChart" width="100%" height="50"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
//SETUP BLOCK
const price = <?php echo json_encode($price); ?>;
const unit_no = <?php echo json_encode($unit_no); ?>;
const data = {
labels: unit_no,
datasets: [{
label: 'Price',
data: price,
backgroundColor: ['rgba(57, 43, 90, .6)'],
borderColor:'rgb(57, 43, 90)',
borderWidth: 2
}]
};
//CONFIG BLOCK
const config = {
type: 'bar',
data,
options: {
scales: {
y: {
beginAtZero: true
}
}
}
};
//RENDER BLOCK
const myBarChart = new Chart(
document.getElementById('myBarChart'),
config
);
</script>
<div class="card-footer small text-muted">Updated yesterday at 11:59 PM</div>
</div>
<div class="row">
<div class="col-lg-6">
<!--LINE CHART-->
<?php
include('config/dbcon.php');
// Attempt select query execution
try{
$linesql = "SELECT * FROM castro_rentals.payment";
$lineresult = $pdo->query($linesql);
if($lineresult->rowCount() > 0) {
$amount = array();
$paymentdate = array();
while($row = $lineresult->fetch()) {
$amount[] = $row["amount"];
$paymentdate[] = $row["paymentdate"];
}
unset($lineresult);
} else {
echo "No records matching your query were found.";
}
} catch(PDOException $e){
die("ERROR: Could not able to execute $linesql. " . $e->getMessage());
}
// Close connection
unset($pdo);
?>
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-chart-line me-1"></i>
Monthly Income
</div>
<div class="card-body">
<canvas id="myLineChart" width="100%" height="50"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
//SETUP BLOCK
const amount = <?php echo json_encode($amount); ?>;
const paymentdate = <?php echo json_encode($paymentdate); ?>;
const data = {
labels: paymentdate,
datasets: [{
label: 'Amount',
data: amount,
backgroundColor: ['rgba(57, 43, 90, .6)'],
borderColor:'rgb(57, 43, 90)',
borderWidth: 2
}]
};
//CONFIG BLOCK
const config = {
type: 'line',
data,
options: {
scales: {
y: {
beginAtZero: true
}
}
}
};
//RENDER BLOCK
const myLineChart = new Chart(
document.getElementById('myLineChart'),
config
);
</script>
<div class="card-footer small text-muted">Updated yesterday at 11:59 PM</div>
</div>
</div>
<!--PIE CHART-->
<div class="col-lg-6">
<!--PIE CHART-->
<?php
include('config/dbcon.php');
// Attempt select query execution
try{
$piesql = "SELECT * FROM castro_rentals.property";
$pieresult = $pdo->query($piesql);
if($pieresult->rowCount() > 0) {
$propertyname = array();
$paymentdate = array();
while($row = $pieresult->fetch()) {
$propertyname[] = $row["propertyname"];
$propertytype[] = $row["propertytype"];
}
unset($pieresult);
} else {
echo "No records matching your query were found.";
}
} catch(PDOException $e){
die("ERROR: Could not able to execute $piesql. " . $e->getMessage());
}
// Close connection
unset($pdo);
?>
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-chart-pie me-1"></i>
# of Property Type
</div>
<div class="card-body">
<canvas id="myPieChart" width="100%" height="50"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
//SETUP BLOCK
const propertyname = <?php echo json_encode($propertyname); ?>;
const propertytype = <?php echo json_encode($propertytype); ?>;
const data = {
labels: propertytype,
datasets: [{
label: 'propertyname',
data: propertyname,
backgroundColor: ['rgba(57, 43, 90, .6)'],
borderColor:'rgb(57, 43, 90)',
borderWidth: 2
}]
};
//CONFIG BLOCK
const config = {
type: 'pie',
data,
options: {
scales: {
y: {
beginAtZero: true
}
}
}
};
//RENDER BLOCK
const myPieChart = new Chart(
document.getElementById('myPieChart'),
config
);
</script>
<div class="card-footer small text-muted">Updated yesterday at 11:59 PM</div>
</div>
</div>
</div>
The only thing I tried to do is to play with the <div> before the <canvas> I thought it wouldn't show because of spacing and size problems but I tried modifying, removing, resizing them, it still didn't show.

How can I toggle specific list items based on catergory?

I have two lists. One contains categories, which are used to group items from a secondary list.
What I am trying to do is to create a toggle, where you click on the name of a category, and then the items for that category will appear. I managed to create the toggle, but the issue is that when I click on a category, it toggles ALL of the other categories as well.
Is there a way of telling Vue to only toggle the items that belongs to the category that is clicked?
Here is my code.
<template>
<b-container>
<b-card class="my-4">
<b-card-title>
<i :class="icons.LIST"></i>
{{ $t('OverviewTitle) }}
</b-card-title>
<loading-message v-if="!quickListCategories"/>
<not-found v-else-if="!filteredQuickListCategories.length"/>
<b-card-text v-else v-for="(category, index) in filteredQuickListCategories"
:key="category.name">
<h5 v-b-toggle.collapse :class="{'mt-4': index}">
<i v-for="(icon, index) in category.icons" :key="index" class="fa-fw" :class="icon"></i>
{{ $t(category.text) }}
</h5>
<b-collapse id="collapse">
<b-list-group>
<b-list-group-item v-for="list in category.lists" :to="list.to">
<i class="fa-fw" :class="list.icon"/> {{ $t(list.text) }}
<div class="mx-4 d-flex w-100 justify-content-between">
<small>{{ $t(list.subText) }}</small>
</div>
</b-list-group-item>
</b-list-group>
</b-collapse>
</b-card-text>
</b-card>
</b-container>
</template>
<script>
import icons from '#/models/entity/icon';
import CommonInput from '#/components/common/CommonInput';
import LoadingMessage from '#/components/LoadingMessage';
import NotFound from '#/views/NotFound';
import {getQuickListCategories} from '#/models/company/quick-lists';
export default {
components: {
CommonInput,
NotFound,
LoadingMessage
},
data() {
return {
icons,
quickListCategories: null
};
},
created() {
this.$title(this.$t('OverviewTitle));
getQuickListCategories()
.then(quickListCategories => this.quickListCategories = quickListCategories)
.catch(() => {
this.quickListCategories = [];
this.$bvModalExt.msgBoxError();
});
}
};
</script>
const quickLists = [
{
icon: icons.LIST,
to: '/list/link1',
area: 'area A',
text: 'Text 1',
categoryName: 'CATEGORY 1',
},
{
icon: icons.LIST,
to: '/list/link2',
area: 'area B',
text: 'Text 2',
categoryName: 'CATEGORY 2',
},
{
icon: icons.LIST,
to: '/list/link3',
area: 'area C',
text: 'Text 3',
categoryName: 'CATEGORY 3',
}
];
const quickListCategories = [
{
icons: ['fas fa-hand-point-right', 'fas fa-store-alt'],
text: 'HEADER 1',
name: 'CATEGORY 1'
},
{
icons: ['fas fa-hand-point-right', 'fas fa-store-alt'],
text: 'HEADER 2',
name: 'CATEGORY 2'
},
{
icons: ['fas fa-hand-point-right', 'fas fa-store-alt'],
text: 'HEADER 3',
name: 'CATEGORY 3'
}
];
export function getQuickListCategories() {
return userService.getCurrentUserAreaPermissionMap().then(({data: userAreaPermissionMap}) =>
quickListCategories
.map(category => ({
...category,
lists: quickLists
.filter(list => list.categoryName === category.name &&
(!list.area || userAreaPermissionMap[list.area] && userAreaPermissionMap[list.area] !== 'NOT_ALLOWED'))
}))
.filter(category => category.lists.length));
console.log(this.lists)
}

Chartjs v. 3.7.1 Zoom out not working after zooming in too much

I am realtively new in front end and Chartjs. My problem is when I zoom in more than a certain point I can not zoom out back. I tried mouse wheel option and added a "zoom out" button but both not working. When I zoom in just a little I dont face the same problem. I tried on Chrome and Edge browsers, both has the same behavior.
CahartJs version: 3.7.1
chartjs-plugin-zoom version: 1.2.0
Note: Second graph is for data decimation which is irrelevant with current problem.
script.js and index.html:
//data creation
let labels2 = [];
let data2 = []
i = 0
k = 0
while (k < 250) {
if (i < 10) {
let last_hall = 600
data2.push(last_hall)
labels2.push(k);
i++
}
if (i >= 10) {
let last_hall = 500
data2.push(last_hall)
labels2.push(k);
i++
if (i == 20) {
for (let j = 0; j < 30; j++) {
let last_hall = getRandomInt(800, 1300)
data2.push(last_hall)
labels2.push(k);
k++
}
i = 0
}
}
k++
}
//data2 = data2.fill(0).map(() => Math.random());
// let labels2 = [];
// let i = 0;
// data2.forEach(element => {
// labels2.push(i);
// i++;
// });
let data3 = [];
data3 = data2;
let labels3 = [];
labels3 = labels2;
ColorArr = ["red", "blue", "red"]
let backgroundColorArr = [];
let backgroundColorArr2 = [];
var ctx = document.getElementById('myChart2').getContext('2d');
var ctx2 = document.getElementById('myChart3').getContext('2d');
const up = (ctx, value) => ctx.p0.parsed.y >= ctx.p1.parsed.y ? value : undefined;
const down = (ctx, value) => ctx.p0.parsed.y < ctx.p1.parsed.y ? value : undefined;
const up2 = (ctx2, value) => ctx2.p0.parsed.y >= ctx2.p1.parsed.y ? value : undefined;
const down2 = (ctx2, value) => ctx2.p0.parsed.y < ctx2.p1.parsed.y ? value : undefined;
data2.forEach(element => {
backgroundColorArr.push(ColorArr[i % 3]);
i++;
});
backgroundColorArr2 = backgroundColorArr;
//Decimation
// if (data3.length > 1000) {
// var datastep = Math.floor(data3.length / 1000) //always show 1000 values from all data
// console.log(datastep);
// for (i = 0; i < 1000; i++) {
// data3[i] = data3[i * datastep];
// backgroundColorArr2[i] = backgroundColorArr2[i * datastep];
// labels3[i] = labels3[i * datastep];
// }
// }
// console.log(labels3)
// data3 = data3.slice(0, 1000);
// labels3 = labels3.slice(0, 1000);
// backgroundColorArr2 = backgroundColorArr2.slice(0, 1000);
let chart3 = new Chart(ctx, {
type: 'line',
data: {
labels: labels2,
datasets: [{
data: data2,
fill: true,
//backgroundColor: backgroundColorArr[ctx.p0DataIndex],
segment: {
borderColor: ctx => up(ctx, 'rgba(75,192,192,1)') || down(ctx, "red"),
backgroundColor: ctx => up(ctx, 'rgba(75,192,192,1)') || down(ctx, "red"), //backgroundColorArr[ctx.p0DataIndex]
},
}]
},
options: {
//parsing: false,
scales: {
x: {
ticks: {
maxTicksLimit: 10,
autoSkip: true,
}
},
y: {
beginAtZero: true
}
},
datasets: {
parsing: false,
line: {
pointRadius: 0 // disable for all `'line'` datasets
}
},
plugins: {
// decimation: {
// algorithm: 'lttb',
// enabled: true,
// samples: 20
// },
zoom: {
pan: {
enabled: true,
mode: 'x',
},
zoom: {
wheel: {
enabled: true,
},
pinch: {
enabled: true
},
mode: 'x',
}
}
}
}
});
let chart2 = new Chart(ctx2, {
type: 'line',
data: {
labels: labels3,
datasets: [{
data: data3,
fill: true,
//backgroundColor: backgroundColorArr[ctx.p0DataIndex],
segment: {
borderColor: ctx2 => up2(ctx2, 'rgba(75,192,192,1)') || down(ctx2, "red"),
backgroundColor: ctx2 => up2(ctx2, 'rgba(75,192,192,1)') || down(ctx2, "red"), //backgroundColorArr[ctx.p0DataIndex],
},
}]
},
options: {
//parsing: false,
scales: {
x: {
ticks: {
maxTicksLimit: 10,
autoSkip: true,
}
},
y: {
beginAtZero: true
}
},
datasets: {
parsing: false,
line: {
pointRadius: 0 // disable for all `'line'` datasets
}
},
plugins: {
// decimation: {
// algorithm: 'lttb',
// enabled: true,
// samples: 20
// },
zoom: {
pan: {
enabled: true,
mode: 'x',
},
zoom: {
//enabled: true,
wheel: {
enabled: true,
},
pinch: {
enabled: true
},
mode: 'x',
}
}
}
}
});
function resetZoom() {
chart2.resetZoom();
}
function resetZoom2() {
chart3.resetZoom();
}
function zoomButton() {
chart2.zoom(1.1);
}
function zoomButton2() {
chart3.zoom(1.3);
}
function zoomOutButton() {
chart2.zoom(0.9);
}
function zoomOutButton2() {
chart3.zoom(0.7);
}
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min) + min); //The maximum is exclusive and the minimum is inclusive
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Charts, Charts, Charts</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="mystyle.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.7.1"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"
integrity="sha512-UXumZrZNiOwnTcZSHLOfcTs0aos2MzBWHXOHOuB0J/R44QB0dwY5JgfbvljXcklVf65Gc4El6RjZ+lnwd2az2g=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/1.2.0/chartjs-plugin-zoom.min.js"
integrity="sha512-TT0wAMqqtjXVzpc48sI0G84rBP+oTkBZPgeRYIOVRGUdwJsyS3WPipsNh///ay2LJ+onCM23tipnz6EvEy2/UA=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
<button onclick="download_csv_file()"> Download CSV </button>
<h1>Charts, Charts, Charts</h1>
<div class="container">
<div class="row">
<div class="col-6 chart">
<canvas id="myChart2" width="1000" height="800"></canvas>
<button onclick="resetZoom2()"> Reset </button>
<button onclick="zoomOutButton2()"> Zoom Out </button>
<button onclick="zoomButton2()"> Zoom In</button>
</div>
</div>
<div class="row">
<div class="col-6 chart">
<canvas id="myChart3" width="1000" height="800"></canvas>
<button onclick="resetZoom()"> Reset </button>
<button onclick="zoomButton()"> Zoom In</button>
<button onclick="zoomOutButton()"> Zoom Out</button>
</div>
<div class="col-6 chart">
<canvas id="myChart4" width="500" height="400"></canvas>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Just had the same problem.
https://github.com/chartjs/chartjs-plugin-zoom/issues/696
Possible solution:
Don't use numbers as labels, use String versions of them
by using .toString() on items of the array.
[1, 2, 3] -> ["1", "2", "3"]

Vue.js - Vuetify - Hard time to test a menu component

Given the following Toolbar component, I am trying to test the locale changing upon click on menu item ... but the wrapper content is not changing after a mouseover event on the menu selector ...
Toolbar.vue
<template>
<v-toolbar height="80px" fixed>
<v-toolbar-title>
<img src="#/assets/images/app_logo.png" alt="">
<v-menu bottom offset-y open-on-hover class="btn btn--flat" style="margin-bottom: 12px;">
<v-btn id="current-flag" flat slot="activator">
<img :src="flagImage(currentLocaleIndex)" width="24px">
</v-btn>
<v-list>
<v-list-tile v-for="(locale, index) in locales" :key="index" #click="switchLocale(index)">
<div class="list__tile__avatar avatar--tile" #click="switchLocale(index)">
<img :src="flagImage(index)" width="24px">
</div>
<div class="list__tile__title" v-html="flagTitle(index)"></div>
</v-list-tile>
</v-list>
</v-menu>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items>
<!-- MENU HOME-->
<v-btn flat #click="$router.push(menuItems.home.link)">
<v-icon left>{{ menuItems.home.icon }}</v-icon>
<span>{{ menuItems.home.title | translate }}</span>
</v-btn>
<!-- ABOUT HOME-->
<v-btn flat #click="$router.push(menuItems.about.link)">
<v-icon left>{{ menuItems.about.icon }}</v-icon>
<span>{{ menuItems.about.title | translate }}</span>
</v-btn>
</v-toolbar-items>
</v-toolbar>
</template>
<script>
// import i18n from '#/locales'
export default {
name: "Toolbar",
props: ["appName"],
data() {
return {
menuItems: {
home: { icon: "home", title: "Home", link: "/" },
about: { icon: "info", title: "About", link: "/about" }
},
locales: [
{ id: "en", title: "English", flag: "#/assets/images/flag_en_24.png" },
{ id: "fr", title: "Français", flag: "#/assets/images/flag_fr_24.png" },
{ id: "br", title: "Português", flag: "#/assets/images/flag_br_24.png" }
]
};
},
computed: {
currentLocaleIndex: function() {
let index = this.locales.findIndex(o => o.id === this.$i18n.locale);
return index;
},
currentLocaleTitle: function() {
let obj = this.locales.find(o => o.id === this.$i18n.locale);
return obj.title;
},
currentLocaleFlag: function() {
let obj = this.locales.find(o => o.id === this.$i18n.locale);
return obj.flag;
}
},
methods: {
flagImage: function(index) {
return require("#/assets/images/flag_" +
this.locales[index].id +
"_24.png");
},
flagTitle: function(index) {
return this.locales[index].title;
},
switchLocale: function(index) {
this.$i18n.locale = this.locales[index].id;
}
},
mounted() {}
};
</script>
Toobar.spec.je
import Vue from "vue";
import router from "#/router";
import Vuetify from "vuetify";
import i18n from "#/locales";
import { mount, shallowMount } from "#vue/test-utils";
import Toolbar from "#/components/shared/Toolbar.vue";
describe("App.vue", () => {
let wrapper;
beforeEach(() => {
Vue.use(Vuetify);
Vue.filter("translate", function(value) {
if (!value) return "";
value = "lang.views.global." + value.toString();
return i18n.t(value);
});
const el = document.createElement('div');
el.setAttribute('data-app', true);
document.body.appendChild(el);
});
it("should change locale", () => {
// given
wrapper = mount(Toolbar, { router, i18n });
console.log('CURRENT LOCALE INDEX: ', wrapper.vm.currentLocaleIndex);
// console.log(wrapper.html());
const currentFlagBtn = wrapper.find("#current-flag");
console.log(currentFlagBtn.html())
currentFlagBtn.trigger('mouseover');
wrapper.vm.$nextTick( () => {
console.log(wrapper.html());
// const localesBtn = wrapper.findAll("btn");
});
// when
// localesBtn.at(1).trigger("click"); // French locale
// then
// expect(wrapper.wrapper.vm.currentLocaleIndex).toBe(1);
});
});
console.log
console.log tests/unit/Toolbar.spec.js:32
CURRENT LOCALE INDEX: 0
console.log tests/unit/Toolbar.spec.js:35
<button type="button" class="v-btn v-btn--flat" id="current-flag"><div class="v-btn__content"><img src="[object Object]" width="24px"></div></button>
console.log tests/unit/Toolbar.spec.js:38
<nav class="v-toolbar v-toolbar--fixed" style="margin-top: 0px; padding-right: 0px; padding-left: 0px; transform: translateY(0px);">
<div class="v-toolbar__content" style="height: 80px;">
<div class="v-toolbar__title">
<img src="#/assets/images/app_logo.png" alt="">
<div class="v-menu btn btn--flat v-menu--inline" style="margin-bottom: 12px;">
<div class="v-menu__activator">
<button type="button" class="v-btn v-btn--flat" id="current-flag">
<div class="v-btn__content">
<img src="[object Object]" width="24px">
</div>
</button>
</div>
</div>
</div>
<div class="spacer"></div>
<div class="v-toolbar__items">
<button type="button" class="v-btn v-btn--flat">
<div class="v-btn__content">
<i aria-hidden="true"class="v-icon v-icon--left material-icons">home</i>
<span>Home</span>
</div>
</button>
<button type="button" class="v-btn v-btn--flat">
<div class="v-btn__content">
<i aria-hidden="true" class="v-icon v-icon--left material-icons">info</i>
<span>About</span>
</div>
</button>
</div>
</div>
</nav>
I found a solution, but maybe someone can explain why :
btnFlags.at(1).vm.$emit('click'); // OK
and
btnFlags.at(1).trigger('click'); // NOT OK
this is the spec which is running fine :
import Vue from "vue";
import router from "#/router";
import Vuetify from "vuetify";
import i18n from "#/locales";
import { mount, shallowMount } from "#vue/test-utils";
import Toolbar from "#/components/shared/Toolbar.vue";
describe("Toolbar.vue", () => {
let wrapper;
beforeEach(() => {
Vue.use(Vuetify);
Vue.filter("translate", function(value) {
if (!value) return "";
value = "lang.views.global." + value.toString();
return i18n.t(value);
});
const el = document.createElement('div');
el.setAttribute('data-app', true);
document.body.appendChild(el);
});
it("should change locale", async () => {
// given
wrapper = shallowMount(Toolbar, { router, i18n });
console.log('CURRENT LOCALE INDEX: ', wrapper.vm.currentLocaleIndex);
const btnFlags = wrapper.findAll("v-list-tile-stub");
// when
btnFlags.at(1).vm.$emit('click');
await wrapper.vm.$nextTick();
// then
console.log('NEW LOCALE INDEX: ', wrapper.vm.currentLocaleIndex);
expect(wrapper.vm.currentLocaleIndex).toBe(1);
});
});

django csrf cookie no longer working

I don't understand why, but Django has ceased including the csrf cookie in responses. I have the middleware enabled, have tried using RequestContext and am using render. I have even tried using the csrf_protect and requires_csrf_token decorators.
I am working on a dev server right now, and I can print the context after I use RequestContext, and it seems to include a csrf_token.
But when I look at the actual headers using Chrome's inspect element, the csrf_token isn't there, also when I use the console and type in "document.cookie" that does not have the csrf token.
HELP!
Here's an example view
#requires_csrf_token
def index(request):
context = RequestContext(request, {'foo':'bar'})
print context
return render(request, 'index.html', context)
The CSRF token seems to be in the context:
{u'csrf_token': <django.utils.functional.__proxy__ object at 0x1025ab990>}, ...
But it fails to make its way through...
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:__utma=96992031.468590559.1369255550.1369255550.1369255550.1; __utmb=96992031.17.10.1369255550; __utmc=96992031; __utmz=96992031.1369255550.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Host:127.0.0.1:8000
Referer:http://127.0.0.1:8000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31
UPDATE: Here is the template I'm using:
{% extends "base.html" %}
{% block hello %}
Basic Stock Event Charts
{% endblock %}
{% block content %}
<div id="leftsidebar">
<p>Use this tool to graph a time series data for a security. You can graph a security and
four other features such as volume, call option volume, or implied volatility. The tool will
zoom in on the date of interest to show the target audience the changes in the selected
vaiables preceeding the event. Because of large movement in variables before the announcement,
it may be helpful to use the minimum and maximum tools to zoom in on smaller movements ahead
of the event. </p>
<div class="ui-widget inline">
<label for="securities">1. Type in a ticker symbol</label>
<input id="securities">
</div>
<div class="inline"><input type="button" id="reload" value="Reset" class="hide" /></div>
<label for="datepicker">2. Pick your event date of interest.</label>
<input type="text" id="datepicker" disabled />
<label>3. Choose other series to graph.</label>
<p><strong>Primary Axis</strong></p>
Left Axis: <select id="series1" class="selectpicker span2" disabled><option value=""></option></select>
<div id="series1minmax" class="hide">
Min <input type="text" id="min1" class="input-mini" />
Max <input type="text" id="max1" class="input-mini" />
</div><input type="button" id="addaxes1" value="Graph" class="hide" />
<input type="button" id="removeaxes1" value="Remove" class="hide" /><br />
<br/>Right Axis: <select id="series2" class="selectpicker span2" disabled><option value=""></option>></select>
<div id="series2minmax" class="hide">
Min <input type="text" id="min2" class="input-mini" />
Max <input type="text" id="max2" class="input-mini" />
</div><input type="button" id="addaxes2" value="Graph" class="hide" />
<input type="button" id="removeaxes2" value="Remove" class="hide" /><br />
<input type="button" id="addextraaxis" value="Add Additional Axis" disabled/><br />
<div id="additional" class="hide">
<p><strong>Additional Axis</strong></p>
Left Axis: <select id="series3" class="selectpicker span2" disabled><option value=""></option></select>
<div id="series3minmax" class="hide">
Min <input type="text" id="min3" class="input-mini" />
Max <input type="text" id="max3" class="input-mini" />
</div><input type="button" id="addaxes3" value="Graph" class="hide" />
<input type="button" id="removeaxes3" value="Remove" class="hide" /><br />
<br/>Right Axis: <select id="series4" class="selectpicker span2" disabled><option value=""></option>></select>
<div id="series4minmax" class="hide">
Min <input type="text" id="min4" class="input-mini" />
Max <input type="text" id="max4" class="input-mini" />
</div><input type="button" id="addaxes4" value="Graph" class="hide" />
<input type="button" id="removeaxes4" value="Remove" class="hide" /><br />
</div>
</div>
<div id="rightsidebar">
<div id="container" class="hide"></div>
</div>
</div>
<script src="http://code.highcharts.com/stock/highstock.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<script src="http://code.highcharts.com/stock/highcharts-more.js"></script>
<script>
$(function() {
$("#removefromchart").click(function() {
var conceptName = $('#savedseries').find(":selected").remove();
});
$("#reload").click(function() {
location.reload();
})
$("#addextraaxis").click(function() {
$("#additional").removeClass("hide");
this.disabled = true
$("#addextraaxis").addClass("hide");
var chart = $("#container").highcharts();
chart.setSize(null, 650);
})
});
$(function() {
$("#series1").change(function() {
$("#addaxes1").removeClass("hide");
});
$("#series2").change(function() {
$("#addaxes2").removeClass("hide");
});
$("#series3").change(function() {
$("#addaxes3").removeClass("hide");
});
$("#series4").change(function() {
$("#addaxes4").removeClass("hide");
});
});
$(function() {
function setExtreme(isMin, axis, value) {
console.log("fired");
var chart = $('#container').highcharts();
if (isMin) {
console.log(value + " " + chart.yAxis[axis].getExtremes()["max"])
chart.yAxis[axis].setExtremes(value, chart.yAxis[axis].getExtremes()["max"]);
} else {
console.log(value + " " + chart.yAxis[axis].getExtremes()["min"])
chart.yAxis[axis].setExtremes(chart.yAxis[axis].getExtremes()["min"], value);
}
console.log(value);
}
function getAxisNumber(series) {
var indicies = {}
$.each(chart.yAxis, function(index, element) {
indicies[element.options.id] = index;
console.log(element.options.id);
});
return indicies[series]
}
$("#max1").change(function() {setExtreme(0, getAxisNumber("#series1"), this.value)});
$("#min1").change(function() {setExtreme(1, getAxisNumber("#series1"), this.value)});
$("#max2").change(function() {setExtreme(0, getAxisNumber("#series2"), this.value)});
$("#min2").change(function() {setExtreme(1, getAxisNumber("#series2"), this.value)});
$("#max3").change(function() {setExtreme(0, getAxisNumber("#series3"), this.value)});
$("#min3").change(function() {setExtreme(1, getAxisNumber("#series3"), this.value)});
$("#max4").change(function() {setExtreme(0, getAxisNumber("#series4"), this.value)});
$("#min4").change(function() {setExtreme(1, getAxisNumber("#series4"), this.value)});
});
$(function()
{
$("#removefromchart").click(function()
{
var conceptName = $('#savedseries').find(":selected").remove();
});
});
$(function() {
function addPlotLine(ts) {
var chart = $('#container').highcharts();
chart.xAxis[0].addPlotBand({
from: ts,
to: ((ts + 86400000) * 365),
color: 'rgba(68, 170, 213, 0.2)',
id: 'tsband'
});
chart.xAxis[0].addPlotLine({
value: ts,
color: 'rgb(255, 0, 0)',
width: 1,
id: 'tsline'
});
chart.xAxis[0].setExtremes(ts - (86400000 * 30), ts + 86400000)
}
function removeEventIfExists() {
var chart = $("#container").highcharts()
chart.xAxis[0].removePlotBand("tsband");
chart.xAxis[0].removePlotLine("tsline");
}
$("#datepicker").datepicker({
showButtonPanel: true, /*added by oussama*/
changeMonth: true, /*added by oussama*/
changeYear: true, /*added by oussama*/
dateFormat: 'yy-mm-dd',
onSelect: function (dateText, inst) {
utcDate = Date.UTC(dateText.split("-")[0], dateText.split("-")[1] - 1, dateText.split("-")[2]);
removeEventIfExists();
addPlotLine(utcDate);
$("#series1").removeAttr("disabled");
$("#series2").removeAttr("disabled");
$("#series3").removeAttr("disabled");
$("#series4").removeAttr("disabled");
$("#addextraaxis").removeAttr("disabled");
var ticker = $("#securities").val();
var date = $("#datepicker").val();
chart.setTitle({text: ticker + " around " + date});
}
});
});
$(function() {
function createChart() {
var chart = $('#container').highcharts();
var options = {chart: {
renderTo: 'container',
height: 450,
},
events: {
load: function(event) {
this.setExtremes();
}
},
rangeSelector: {
enabled: false,
},
exporting: {
enabled: false,
},
navigator: {
enabled: true,
series: { id: 'navigator' },
},
yAxis: [{
title: {
text: 'Price'
},
height: 150,
}],
},
chart = new Highcharts.StockChart(options);
return chart;
}
$("#securities").autocomplete({
source: "/api/get_securities/",
minLength: 1,
select: function(event, ui) {
var ticker = ui.item.label;
getSeries(ticker);
chart = createChart();
getTimeSeriesData(ticker + "|PX_LAST", 0);
$('#container').show();
$('#datepicker').removeAttr("disabled");
$('#reload').removeClass("hide");
chart.setTitle({text: ticker});
this.disabled = 'disabled';
},
});
});
$(function() {
function removeAxes(id) {
var chart = $('#container').highcharts();
chart.get(id).remove();
}
$("#removeaxes1").click(function() {
console.log("removeaxes1 clicked");
removeAxes("#series1");
$("#removeaxes1").addClass("hide");
$("#series1minmax").addClass("hide");
$("#series1minmax").removeClass("inline");
$("#series1").val("");
$("#min1").val("");
$("#max1").val("");
$("#series1").removeAttr("disabled");
});
$("#removeaxes2").click(function() {
console.log("removeaxes2 clicked");
removeAxes("#series2");
$("#removeaxes2").addClass("hide");
$("#series2minmax").addClass("hide");
$("#series2minmax").removeClass("inline");
$("#series2").val("");
$("#min2").val("");
$("#max2").val("");
$("#series2").removeAttr("disabled");
});
$("#removeaxes3").click(function() {
console.log("removeaxes3 clicked");
removeAxes("#series3");
$("#removeaxes3").addClass("hide");
$("#series3minmax").addClass("hide");
$("#series3minmax").removeClass("inline");
$("#series3").val("");
$("#min3").val("");
$("#max3").val("");
$("#series3").removeAttr("disabled");
});
$("#removeaxes4").click(function() {
console.log("removeaxes4 clicked");
removeAxes("#series4");
$("#removeaxes4").addClass("hide");
$("#series4minmax").addClass("hide");
$("#series4minmax").removeClass("inline");
$("#series4").val("");
$("#min4").val("");
$("#max4").val("");
$("#series4").removeAttr("disabled");
});
function addSeries(id, minMaxId, isOpposite, isAdditional) {
var chart = $('#container').highcharts();
indicies = {}
console.log('climlckedaddaxes');
var series = $(id).val()
var top = 210
if (isAdditional) top = 380
var options = {
title: {
text: series.split("|")[1]
},
top: top,
height: 150,
opposite: isOpposite,
id: id,
offset: -30
}
chart.addAxis(options)
$.each(chart.yAxis, function(index, element) {
indicies[element.options.id] = index;
console.log(element.options.id);
});
getTimeSeriesData(series, indicies[id]);
$(minMaxId).removeClass("hide")
$(minMaxId).addClass("inline")
}
$("#addaxes1").click(function() {
addSeries('#series1', "#series1minmax", false, false);
$("#addaxes1").addClass("hide")
$("#removeaxes1").removeClass("hide")
$("#series1").attr("disabled", "disabled")
});
$("#addaxes2").click(function() {
addSeries('#series2', "#series2minmax", true, false);
$("#addaxes2").addClass("hide")
$("#removeaxes2").removeClass("hide")
$("#series2").attr("disabled", "disabled")
});
$("#addaxes3").click(function() {
addSeries('#series3', "#series3minmax", false, true);
$("#addaxes3").addClass("hide")
$("#removeaxes3").removeClass("hide")
$("#series3").attr("disabled", "disabled")
});
$("#addaxes4").click(function() {
addSeries('#series4', "#series4minmax", true, true);
$("#addaxes4").addClass("hide")
$("#removeaxes4").removeClass("hide")
$("#series4").attr("disabled", "disabled")
});
})
$('#addtochart').click(function() {
var selectedValues = $('#seriesselector').val();
$.each(selectedValues, function(index, value) {
$('#savedseries').append($('<option>', {
value: value,
text: value,
selected: true,
}));
$('#seriesselector option[value="' + value +'"]').remove();
});
});
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function parseDate(inputdate, value) {
var date = inputdate;
var year = parseInt(date.split("-")[0]);
var month = parseInt(date.split("-")[1]) - 1;
var day = parseInt(date.split("-")[2]);
var outputdate = Date.UTC(year, month, day);
if (year == 2013 && month == 3) {
//console.log(inputdate, outputdate, value);
}
return outputdate;
};
function getTimeSeriesData(seriesName, axis) {
var csrftoken = getCookie('csrftoken');
console.log('csrftoken is :: ' + csrftoken);
$.ajax({ // create an AJAX call...
beforeSend: function(xhr, settings) {
var csrftoken = getCookie('csrftoken');
xhr.setRequestHeader("X-CSRFToken", csrftoken);
},
data: {'seriesName': seriesName }, // get the form data
type: 'POST',
url: '/api/get_time_series_data/',
success: function(response) { // on success..
console.log(response);
var series = {}
series['name'] = response[0]['series_name'];
series['data'] = []
$.each(response, function(index, value) {
series['data'][index] = [
parseDate(response[index]['date'], response[index]['value']),
parseFloat(response[index]['value'])
];
});
series['yAxis'] = axis
series['marker'] = {
enabled : true,
radius : 3
}
var chart = $('#container').highcharts();
chart.addSeries(series);
var nav = chart.get('navigator');
if (axis == 0) nav.setData(series['data']);
}
});
return false;
};
function getSeries(ticker) {
var csrftoken = getCookie('csrftoken');
$.ajax({ // create an AJAX call...
beforeSend: function(xhr, settings) {
var csrftoken = getCookie('csrftoken');
xhr.setRequestHeader("X-CSRFToken", csrftoken);
},
data: {'ticker': ticker }, // get the form data
type: 'POST',
url: '/api/get_series/',
success: function(response) { // on success..
$('#seriesselector').empty()
for (var i = 0; i < response.length; i++) {
if (response[i].value == 'PX_LAST') continue;
$('#series1').append($('<option>', {
value: ticker + "|" + response[i].value,
text: response[i].value
}));
$('#series2').append($('<option>', {
value: ticker + "|" + response[i].value,
text: response[i].value
}));
$('#series3').append($('<option>', {
value: ticker + "|" + response[i].value,
text: response[i].value
}));
$('#series4').append($('<option>', {
value: ticker + "|" + response[i].value,
text: response[i].value
}));
}
}
});
return false;
};
</script>
{% endblock %}
Turns out you need the
{% csrf_token %}
regardless of whether or not you are posting a html form. I was only doing AJAX requests, but Django won't include the token in the response header unless it sees it the template.