With vue, I create a json file with classic asp from Sql Server and import the data. My goal is to place the data I have received on the page and in apexCharts.
The html page I used, getData.js and json from dataSql.asp is as follows.
index.html
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="vue.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script>
<style> textarea { position: fixed; right: 0; top: 0; width: 300px; height: 400px; } </style>
</head>
<body>
<div id="app">
<form id="urlParameterForm">
<input type="date" name="startDate" id="startDate" />
<input type="date" name="endDate" id="endDate" />
<input
type="number"
name="pageNumber"
id="pageNumber"
value="1"
v-on:input="changePage"
/>
<input
type="button"
value="Filter"
id="Filter"
v-on:click="changeFilter"
/>
<p>Page : {{ pageActive }}</p>
</form>
<h3>{{title}}</h3>
<div v-for="dta in dataTable.sqlData">
Height: {{dta.height}}, Type: {{dta.type}}
<ul v-for="dta in dataTable.sqlData.graphData">
<li>{{dta.categorie}} - {{dta.serie}}</li>
</ul>
</div>
<textarea>
{{dataTable}}
</textarea>
</div>
<script src="getData.js"></script>
</body>
</html>
getData.js
const app = new Vue({
el: "#app",
devtools: true,
data: {
dataTable: [],
pageNumber: 1,
pageActive :0,
title:'Graph-1'
},
computed: {
url() {
return './dataSql.asp?pg=' + this.pageNumber
}
},
methods: {
changePage: function (event) {
console.log('Change Page',this.pageNumber);
this.pageNumber = event.target.value;
this.init();
},
changeFilter: function (event) {
console.log('Change Filter');
this.init();
},
init() {
let that = this;
console.log('init call');
$.ajax({
type: "POST",
url: that.url,
data:{
startDate:$('#startDate').val(),
endDate:$('#endDate').val(),
pageNumber:$('#pageNumber').val()
},
success: function (data) {
console.log('data remote call');
console.log(data.sqlData);
that.dataTable = data.sqlData;
}
});
}
},
mounted() {
this.init()
}
})
dataSql.asp response json
[
{
"height": 350,
"type": "bar",
"graphData": [
{
"categorie": "Bursa",
"serie": 4
},
{
"categorie": "Tekirdağ",
"serie": 3
}
]
}
]
When I run the page, the screen calls the data like this and I see the data coming as json.
Under the graph-1 text, the does not show anything as if I have never written this. But I can print json text in the text field as it appears in the upper right corner.
<div v-for="dta in dataTable.sqlData">
Height: {{dta.height}}, Type: {{dta.type}}
<ul v-for="dta in dataTable.sqlData.graphData">
<li>{{dta.categorie}} - {{dta.serie}}</li>
</ul>
</div>
<textarea>
{{dataTable}}
</textarea>
I actually want to assign this data, which I could not show on the page, to x and y variables here.
I need something like the following.
categories: app.dataTable.graphData.categorie;
series: app.dataTable.graphData.serie;
var barBasicChart = {
chart: {
height: 350,
type: 'bar',
},
plotOptions: {
bar: {
horizontal: true,
}
},
dataLabels: {
enabled: false
},
series: [{
data: [4,3] /* vue - json - graphData.serie */
}],
xaxis: {
categories: ['Bursa','Tekirdağ'], /* vue - json - graphData.categories */
},
fill: {
colors: $themeColor
}
}
// Initializing Bar Basic Chart
var bar_basic_chart = new ApexCharts(
document.querySelector("#denemeGrafik"),
barBasicChart
);
bar_basic_chart.render();
Vue seems to have not been developed for a long time. I'm new to vuede too. My goal is to automatically generate html content from json. To change the variables of the scripts I have used (such as apexcharts, xGrid etc.).
Can you suggest if there is another javascript library that I can do these things with?
Except for React and Angular because these two are hard to understand and write.
Your AJAX callback assigns dataTable to data.sqlData:
$.ajax({
//...
success: function (data) {
that.dataTable = data.sqlData;
}
})
Then, your component tries to render dataTable.sqlData, but sqlData was already extracted in the AJAX callback (dataTable is an Array):
<div v-for="dta in dataTable.sqlData">
^^^^^^^ ❌
Solution: You can either update the AJAX callback to return the full response (including sqlData):
$.ajax({
//...
success: function (data) {
that.dataTable = data;
}
})
...or update the template to not dereference sqlData, using dataTable directly:
<div v-for="dta in dataTable">
Related
I am trying to find a solution that generates PDF using HTML template and be able to send it on WhatsApp. I am using pdf-creator-node but I am not able to send this PDF to WhatsApp.
I tried using get-stream but it gives source.on('error', function() {}); error.
index.js
var pdf = require("pdf-creator-node");
var fs = require("fs");
let wa = require("./sendTemplate")
require("dotenv").config()
const getStream = require('get-stream')
// Read HTML Template
async function createCertificate() {
var html = fs.readFileSync("template.html", "utf8")
var options = {
format: "A3",
orientation: "portrait",
border: "10mm",
header: {
height: "45mm",
contents: '<div style="text-align: center;">Author: Shyam Hajare</div>'
},
footer: {
height: "28mm",
contents: {
first: 'Cover page',
2: 'Second page', // Any page number is working. 1-based index
default: '<span style="color: #444;">{{page}}</span>/<span>{{pages}}</span>', // fallback value
last: 'Last Page'
}
}
};
var users = [
{
name: "Shyam",
age: "26",
},
{
name: "Navjot",
age: "26",
},
{
name: "Vitthal",
age: "26",
},
];
var document = {
html: html,
data: {
users: users,
},
path: "./output.pdf",
type: "",
};
pdf
.create(document, options)
.then(async (res) => {
console.log(res);
resolve(await getStream.buffer(document))
})
.catch((error) => {
console.error(error);
});
}
const pdfBuffer = createCertificate()
wa.sendMedia(pdfBuffer, "name_output.pdf", "number")
template.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Hello world!</title>
</head>
<body>
<h1>User List</h1>
<ul>
{{#each users}}
<li>Name: {{this.name}}</li>
<li>Age: {{this.age}}</li>
<br />
{{/each}}
</ul>
</body>
</html>
I am using WATI as my WhatsApp API provider
YouTube reference: https://www.youtube.com/watch?v=SCQzIRNT-eU&ab_channel=CodingShiksha
I am using flask to develop my website and i often have to use graph to display data, so I'd like to have a route that display a graph and then use it as a template. The way I found to do it is the following:
Two html files : tender.html and template.html with the first one used as the file to display to the user and the second one used as a template for graph that can be re-used in other routes
template.html :
<!DOCTYPE html>
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.0.0/dist/chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#2.0.0"></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.1/chartjs-plugin-zoom.min.js" integrity="sha512-klQv6lz2YR+MecyFYMFRuU2eAl8IPRo6zHnsc9n142TJuJHS8CG0ix4Oq9na9ceeg1u5EkBfZsFcV3U7J51iew==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div class="chart-container" style=""><canvas id="myChart-1"></canvas></div>
<div>div-test</div>
<script>
const dataset_1 = [{
label: "Spread of ",
type: 'line',
backgroundColor: "blue",
order : 3,
pointRadius:0,
borderWidth: 1,
borderWidth: 1,
borderColor:"blue",
data: {{ data | safe }},
yAxisID: 'y'
},
];
const data_1 = {
labels: {{ label | safe }},
datasets : dataset_1
};
const zoomOptions = {
animations: false,
tranistions: false,
pan: {
enabled: true,
mode: 'x',
},
zoom: {
wheel: {
enabled: true,
},
drag: {
enabled: true,
modifierKey: 'ctrl',
},
mode: 'x',
onZoomComplete({chart}) {
// This update is needed to display up to date zoom level in the title.
// Without this, previous zoom level is displayed.
// The reason is: title uses the same beforeUpdate hook, and is evaluated before zoom.
chart.update('none');
}
}
};
const config_1 = {
data: data_1,
options: {
animations:false,
transitions:false,
responsive: true,
interaction: {
},
stacked: false,
plugins: {
zoom : zoomOptions,
title: {
display: true,
text: "bla bla"
}
},
scales: {
y: {
type: 'linear',
display: true,
position: 'left',
borderWidth : 0.001,
},
x: {
display: true,
grid :{
display:false
},
},
},
},
};
const myChart_1 = new Chart(document.getElementById('myChart-1'),config_1);
</script>
tender.html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
{% autoescape false %}
{{template}}
{% endautoescape %}
</body>
</html>
The route in my flask app that "join" the two files
#app.route('/test')
def test():
template = render_template('template.html',data=[2,4,1,9,5,2],label=[0,1,2,3,4,5])
return render_template('tender.html', template=template)
Obviously this solution is completely fine but i thought that render_template was meant to only be used with return, at the end of routes so i was wondering wether there was a more natural or prettier way to do the job. I was thinking there was as i have to use autoescape on my template variable to have my stuff rendered.
Thanks for your help already and I can clarify my point if it isn't clear enough !
I'm using a vue component which is two way bound with an input field.
I want to append a +- and a % sign to this value solely in the input field view. I don't want to change the actual value as this will cause troubles with the component.
Here is what I am looking for:
Here is what I have:
Using this code:
<form class="form-container">
<label for="changePercent" class="move-percent-label">Move Market</label>
<input class="move-percent" id="changePercent" v-model="value.value" type="number">
<span class="middle-line"></span>
<vue-slider v-bind="value" v-model="value.value"></vue-slider>
<div class="control-buttons">
<button #click="" class="primary-button">Apply</button>
<button #click.prevent="value.value = 0;" class="tertiary-button">Reset</button>
</div>
</form>
------------------UPDATE-------------------
As per answer below using a computed property.
Good:
Not Good
So I need this to work both ways
To have another value always formated a computed property:
new Vue({
el: '#app',
data: {
value: {value: 0},
// ..
},
computed: {
readableValue() {
return (this.value.value => 0 ? "+" : "-" ) + this.value.value + "%";
}
}
})
Creating an editor for the slider and showing formatted
To get what you want we will have to do a litte trick with two inputs. Because you want the user to edit in a <input type="number"> but want to also show +15% which can't be shown in a <input type="number"> (because + and % aren't numbers). So you would have to do some showing/hiding, as below:
new Vue( {
el: '#app',
data () {
return {
editing: false,
value: {value: 0},
}
},
methods: {
enableEditing() {
this.editing = true;
Vue.nextTick(() => { setTimeout(() => this.$refs.editor.focus(), 100) });
},
disableEditing() {
this.editing = false;
}
},
computed: {
readableValue() {
return (this.value.value > 0 ? "+" : "" ) + this.value.value + "%";
}
},
components: {
'vueSlider': window[ 'vue-slider-component' ],
}
})
/* styles just for testing */
#app { margin: 10px; }
#app input:nth-child(1) { background-color: yellow }
#app input:nth-child(2) { background-color: green }
<div id="app">
<input :value="readableValue" type="text" v-show="!editing" #focus="enableEditing">
<input v-model.number="value.value" type="number" ref="editor" v-show="editing" #blur="disableEditing">
<br><br><br>
<vue-slider v-model="value.value" min="-20" max="20">></vue-slider>
</div>
<script src="https://unpkg.com/vue#2.5.13/dist/vue.min.js"></script>
<script src="https://nightcatsama.github.io/vue-slider-component/dist/index.js"></script>
I'm doing assignment, and essentially what I would like to do it have an autocomplete on the input box so the user can select a 'Starter' and 'Main' from a JSON file. When inputting characters, a dropdown list is displayed, but it is not populated with values.
The JSON file (spanish.php) is:
([{"course":"starter","name":"Chorizo Sausage Rolls","price":"5.99"},{"course":"starter","name":"Sardines in Lemon Sauce","price":"6.99"},{"course":"starter","name":"Spanish Tortilla","price":"5.99"},{"course":"starter","name":"Escabeche","price":"4.99"},{"course":"main","name":"Seafood Paella","price":"13.99"},{"course":"main","name":"Albondigas Soup","price":"9.99"},{"course":"main","name":"Linguine with Mussels","price":"13.99"},{"course":"main","name":"Spanish Rice with Shrimp","price":"11.99"},{"course":"main","name":"Roasted Red Pepper Salad","price":"8.99"},{"course":"main","name":"Chorizo Fritatta","price":"10.99"},{"course":"main","name":"Lamb Meatballs","price":"12.99"}]);
Here is my code:
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<script type="text/javascript">
$( function() {
$( "#starter" ).autocomplete({
source: function( request, response ) {
$.ajax( {
url: "http://learn.cf.ac.uk/webstudent/sem5tl/javascript/assignments/spanish.php",
dataType: "jsonp",
data: {
term: request.term
},
success: function( data ) {
response( data );
}
} );
},
minLength: 2,
} );
} );
</script>
And the HTML:
<label for="starter">Choose starter</label>
<input type="text" name="starter" id="starter"><br>
<label for="main">Choose main</label>
<input type="text" name="main" id="main"><br>
As I said, the list is returning nothing when 2+ digits are entered. Do I need to ask for it just starters? Am I goin about this correctly? I will be asking the user to choose a starter and main, then submitting the form.
Thanks.
I'm giving here a solution for auto-completing the starter menu. Hope that you can do the same for main menu searching. Or comment in this answer, if you're facing any problem implementing this.
<!doctype html>
<html lang="en">
<head>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
var starterSearchData;
$(function() {
$.ajax({
url: "http://learn.cf.ac.uk/webstudent/sem5tl/javascript/assignments/spanish.php",
dataType: "jsonp",
async: false,
success: function(data) {
starterSearchData = $.map(data, function(item) {
if (item.course == "starter")
return item.name;
});
EnableAutoComplete();
},
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert(err.Message);
}
});
function EnableAutoComplete() {
$("#starter").autocomplete({
source: starterSearchData,
minLength: 2,
delay: 100
});
}
});
</script>
</head>
<body>
<label for="starter">Choose starter</label>
<input type="text" name="starter" id="starter">
</body>
</html>
http://demos.telerik.com/kendo-ui/mobile/listview/pull-with-endless.html refering this demo we are creating kenolistview for our mobile application.
we are getting data form webapi in jSon, whend we try to bind data with list view it's giving errors we tried three methods but all are not working, please find code bellow and error bellow code.
<body>
<div data-role="view" data-init="mobileListViewPullWithEndless" data-title="Pull to refresh">
<header data-role="header">
<div data-role="navbar">
<span data-role="view-title"></span>
<a data-align="left" data-icon="add" data-role="button" data-rel="modalview" href="#modalview-add"></a>
<a data-align="right" data-role="button" class="nav-button" href="#/">Index</a>
</div>
</header>
<ul id="pull-with-endless-listview">
</ul>
</div>
<div data-role="modalview" id="modalview-add" style="width: 95%; height: 12em;">
<div data-role="header">
<div data-role="navbar">
<span>Add Product</span> <a data-click="closeModalViewAdd" data-role="button" data-align="right">
Cancel</a>
</div>
</div>
<ul data-role="listview" data-style="inset">
<li>
<label for="username">
Product Category:</label>
<input type="text" id="name" /></li>
</ul>
<a data-click="addNew" class="addNew" type="button" data-role="button">Add New Product</a>
</div>
<script type="text/x-kendo-tmpl" id="pull-with-endless-template">
<div class="product-item">
<h3>#:CatName#</h3>
</div>
</script>
<script>
function mobileListViewPullWithEndless(e) {
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "http://mydomain.com/api/homescreenapp/36/8c177908-be9f-4474-b036-43e8cef736b5/345/800/web",
dataType: 'JSON'
}
},
serverPaging: true,
pageSize: 2
});
$("#pull-with-endless-listview").kendoMobileListView({
dataSource: dataSource,
template: $("#pull-with-endless-template").text(),
pullToRefresh: true,
endlessScroll: true
});
$("#addNew").click(function () {
loader.show();
addProductDataSource.add({
ProductName: $("#name").val(),
UnitPrice: Math.floor((Math.random() * 10) + 1)
});
});
}
function closeModalViewAdd() {
$("#modalview-add").kendoMobileModalView("close");
}
function addNew() {
addProductDataSource.add({
ProductName: $("#name").val(),
UnitPrice: Math.floor((Math.random() * 10) + 1)
});
closeModalViewAdd();
}
var addProductDataSource = new kendo.data.DataSource({
transport: {
create: {
url: " http://mydomain.com/api/homescreenapp/36/8c177908-be9f-4474-b036-43e8cef736b5/345/800/web",
dataType: "jsonp"
},
parameterMap: function (options, operation) {
if (operation !== "read" && options.models) {
return { models: kendo.stringify(options.models) };
}
}
},
schema: {
model: {
id: "ProductID",
fields: {
ProductID: { editable: false, nullable: true },
ProductName: { type: "string" }
}
}
},
autoSync: true,
batch: true,
requestEnd: function () {
$("#name").val("");
}
});
</script>
<script>
window.kendoMobileApplication = new kendo.mobile.Application(document.body);
</script>
</body>
We are getting following jSon response from our webapi
{"Categories":[{"CategoryId":"305","CatName":"Clothing","Description":"","ParentId":"0","ImageName":"http://mydomailn.com/customerassets/company36/UploadImages/Category/ResizeImage/345webMan&woman.jpg","MapUrlRewrite":"Clothing"},{"CategoryId":"306","CatName":"Shoes","Description":"","ParentId":"0","ImageName":"http://mydomailn.com/customerassets/company36/UploadImages/Category/ResizeImage/345web2.jpg","MapUrlRewrite":"Shoes"},{"CategoryId":"307","CatName":"Handbags","Description":"","ParentId":"0","ImageName":"http://mydomailn.com/customerassets/company36/UploadImages/Category/ResizeImage/345web3.jpg","MapUrlRewrite":"Handbags"},{"CategoryId":"308","CatName":"Accesories","Description":"","ParentId":"0","ImageName":"http://mydomailn.com/customerassets/company36/UploadImages/Category/ResizeImage/345web4.jpg","MapUrlRewrite":"Accesories"},{"CategoryId":"309","CatName":"Luggage","Description":"","ParentId":"0","ImageName":"http://mydomailn.com/customerassets/company36/UploadImages/Category/ResizeImage/345web5.jpg","MapUrlRewrite":"Luggage"},{"CategoryId":"310","CatName":"Jewellery","Description":"","ParentId":"0","ImageName":"http://mydomailn.com/customerassets/company36/UploadImages/Category/ResizeImage/345web6.jpg","MapUrlRewrite":"Jwellery"},{"CategoryId":"344","CatName":"Eye Wear","Description":"","ParentId":"0","ImageName":"http://mydomailn.com/customerassets/company36/UploadImages/Category/ResizeImage/345web7.jpg","MapUrlRewrite":"Eye-Wear"},{"CategoryId":"345","CatName":"Watches","Description":"","ParentId":"0","ImageName":"http://mydomailn.com/customerassets/company36/UploadImages/Category/ResizeImage/345web8.jpg","MapUrlRewrite":"Top-Brands"},{"CategoryId":"346","CatName":"Hot Brands","Description":"","ParentId":"0","ImageName":"http://mydomailn.com/customerassets/company36/UploadImages/Category/ResizeImage/345webHot_Brands.jpg","MapUrlRewrite":"Hot-Deals--Offers"}],"HomeBannerImages":[{"ImageName":"http://mydomailn.com/customerassets/company36/UploadImages/Banners/ResizeImage/800webBanner_1.jpg","BannerTitle":"Banner Clothing","BannerDescription":"","CategoryId":null},{"ImageName":"http://mydomailn.com/customerassets/company36/UploadImages/Banners/ResizeImage/800webshoes-banner_2.jpg","BannerTitle":" shoes banner","BannerDescription":"","CategoryId":null},{"ImageName":"http://mydomailn.com/customerassets/company36/UploadImages/Banners/ResizeImage/800webhandbag-banner1.jpg","BannerTitle":"handbag ","BannerDescription":"","CategoryId":null},{"ImageName":"http://mydomailn.com/customerassets/company36/UploadImages/Banners/ResizeImage/800webLuggage_2.jpg","BannerTitle":"Laggege","BannerDescription":"","CategoryId":null},{"ImageName":"http://mydomailn.com/customerassets/company36/UploadImages/Banners/ResizeImage/800webjewelry_2.jpg","BannerTitle":"jewelry","BannerDescription":"","CategoryId":null}],"CustomerLogo":"http://mydomailn.com/iconnect/Images/eapparelCustomerLogo12.png"}
Code and Error :
With above code if we bind kendoMobileListView we are getting error "Uncaught SyntaxError: Unexpected token"
if we use dataType: “json” instead of dataType: “jsonp”, I am getting error like "Uncaught TypeError: Cannot call method 'slice' of undefined"
If we use dataType: “json” instead of dataType: “json array”, it is not displaying anything in listing and even in error. It mean all things will be blank.
We have gone through with all below parameter. But still not getting any success.
dataType: 'JSONP',
jsonpCallback: 'jsonCallback',
type: 'GET',
async: false,
crossDomain: true
Please guide me on this issue, I need to bind only Category name in the list.
FYI : i cann't change webapi response as it's being used by other services of client.
Thanks,
Ashish
Kendo expects the server to return a JSON array. In your case it returns an object with a Categories property where the data array is stored. You need to tell the Kendo DataSource to pull the data from .Categories using the schema.data configuration option.
... = new DataSource({
...
schema: {
data: "Categories"
}
});