Convert index.html to complete Vue CLI structure - javascript

I created this app to calculate cube of a number and then cube of the individual elements of the output. I created this Vue js project in JS Fiddle to learn the basics of Vue. But I want to move to complete Vue CLI project. I installed Vue.js in my computer but I can't figure out how to port this single file index.html into the different files in Vue CLI project (App.vue, HelloWorld.vue, main.js). Can anyone tell me how exactly to convert this single page file to the actual project files.
<div id="cubed">
<input v-model='mainNumber' placeholder='Enter a number.'>
<button v-on:click="cube">Submit</button>
<p>
Cube of the number is: {{ this.result }} <br>
</p>
<table id="table">
<tr v-for="row in 2" :key="item">
<td v-for="item in result" v-text="row > 1 ? cubeInt(item) : item"></td>
</tr>
</table>
</div>
#table {
border-collapse: collapse;
width: 50%;
text-align: center;
}
#table td, #customers th {
border: 1px solid #ddd;
padding: 8px;
}
#table tr:nth-child(even){background-color: #f2f2f2;}
#table tr:hover {background-color: #ddd;}
new Vue({
el: "#cubed",
data: {
mainNumber: null,
result: null
},
methods: {
cubeInt: function(int) {
return int*int*int
},
cube: function(event){
var allowedInput = /^[0-9]/;
if (this.mainNumber.match(allowedInput)){
let calc = this.cubeInt(this.mainNumber);
let strToNum = calc.toString().split('').map(Number);
this.result = strToNum
} else {
alert('Only digits are allowed.');
}
},
}
})

So using the Vue cli we have vue files, each file has a
template
script
style (optional)
I recommend checking out: The Project Anatomy section of this site:
https://www.sitepoint.com/vue-cli-intro/
And checkout some tutorials from netninja on youtube, they're really helpful!
If you want to get it working now, but are stuck on importing components etc, as a test, replace and save the HelloWorld.vue file with below your below vue format code:
<template>
<div id="cubed">
<input v-model='mainNumber' placeholder='Enter a number.'>
<button v-on:click="cube">Submit</button>
<p>
Cube of the number is: {{ this.result }} <br>
</p>
<table id="table">
<tr v-for="row in 2" :key="item">
<td v-for="item in result" v-text="row > 1 ? cubeInt(item) : item"></td>
</tr>
</table>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data: {
mainNumber: null,
result: null
},
methods: {
cubeInt: function(int) {
return int*int*int
},
cube: function(event){
var allowedInput = /^[0-9]/;
if (this.mainNumber.match(allowedInput)){
let calc = this.cubeInt(this.mainNumber);
let strToNum = calc.toString().split('').map(Number);
this.result = strToNum
} else {
alert('Only digits are allowed.');
}
},
}
}
</script>
<style scoped>
#table {
border-collapse: collapse;
width: 50%;
text-align: center;
}
#table td, #customers th {
border: 1px solid #ddd;
padding: 8px;
}
#table tr:nth-child(even){background-color: #f2f2f2;}
#table tr:hover {background-color: #ddd;}
</style>

Related

Unique content in each component in v-for

Program description: I'm making a simple timetable program with Vue.js. The page has a "calendar" (a table of 7 columns, where each column correspond to a specific date) and a button on the bottom of each calendar column. On clicking a button a modal should pop up with a specific date in its body-content. The date in the body-content of the modal should be the same as in date in the column title, where the button is placed. Dates can also be changed on click of a forward or backward button. When clicking forward all dates shift one day forward. In case of backward all dates shift one day backward.
Approach to the program: I have a parent component App.vue and a child component for the modal modal.vue. In the parent component as one of the attributes I have array dateArr which contains 7 different dates in the following format: ['9/11/21', '9/12/21', ..., '15/11/21']. On App.vue mount getDatesArray method is being called which fills dateArr attribute with dates. On clicking backward and forward currentOffset is being changed and getDatesArray method is being triggered. The first row of the table consists of dates, therefore I create it with v-for and iterate over each date in dateArr. The body of the table consists of 3 rows in each column. The last row in each column contains a unique button and a modal. In the last row I want to bind each component to a specific date, so I yet again iterate over each date in dateArr. The modal component has a slot in it, where I put unique date from dateArr. On click of the button the visibility of the modal changes with change method.
Problem: Everything works well, however, whatever button I click, the content (date) of the modal component stays the same: 15/11/21, which is the last element of the array. The purpose of the program is to have unique content (date) inside each modal component with the core attribute (dateArr) being dynamic. I've tried implementing different solutions to this problem, but none were of use. I will really appreciate any help!
App.vue:
<template>
<table class = 'dataFrame'>
<thead>
<tr>
<th v-for="item in dayArr" :key="item.id">
{{item}}
</th>
</tr>
</thead>
<tbody>
<tr v-for="index in [1,2,3]" :key="index">
<td v-for="item_index in dayArr.length" :key="item_index">
Dummy content
</td>
</tr>
<tr>
<td v-for="date in dayArr" :key="date.id">
<button #click="change">+</button>
<modal-component #changevisibility="change" v-if="modalToggled">
<p>{{ date }}</p>
</modal-component>
</td>
</tr>
</tbody>
</table>
<div class="buttonSection">
<button #click="currentOffset --" class="back" v-show="currentOffset >= -7">forward</button>
<button #click="currentOffset ++" class="forward" v-show="currentOffset <= 7">backward</button>
</div>
</template>
<script>
import basecard from './components/card.vue'
import navbarComponent from './components/menu.vue'
import modalComponent from './components/modal.vue'
export default {
data() {
return {
currentOffset: 0,
modalToggled : false,
dayArr: []
}
},
methods: {
change() {
this.modalToggled = !this.modalToggled
},
getDatesArray() {
let date = new Date();
date.setDate(date.getDate() + this.currentOffset);
let dayArr = [];
for (let i = 0; i < 7; i++) {
let customDateArray = new Intl.DateTimeFormat('en-GB', { day: 'numeric', month: 'short', year: 'numeric', hour: 'numeric', minute: 'numeric' }).formatToParts(date)
let dateParts = {}
customDateArray.map(({type, value}) => {
dateParts[type] = value
})
dayArr.push(`${dateParts.day}/${date.getMonth()+1}/${dateParts.year.slice(-2)}`)
date.setDate(date.getDate() + 1);
}
this.dayArr = dayArr
}
},
mounted () {
this.getDatesArray()
},
watch: {
currentOffset () {
this.getDatesArray()
}
},
name: 'App',
components: {
modalComponent
}
}
</script>
<style>
#app {
display: flexbox;
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50
}
.dataFrame {
border: 2px solid;
width: 100%;
border-color: #2c3e50;
}
.buttonSection {
margin-top: 1rem;
width: 100%;
max-height: 100%;
}
.back {
float: left;
}
.forward {
float: right;
}
</style>
modal.vue:
<template>
<div class="modal">
<div class="modal-content">
<slot></slot>
<button #click="changeVisibilityFromComponent">
<span class="close">Close ×</span>
</button>
</div>
</div>
</template>
<script>
export default {
name: 'modalComponent',
methods: {
changeVisibilityFromComponent () {
this.$emit('changevisibility')
},
}
}
</script>
<style scoped>
.modal {
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0,0.4);
}
.modal-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
}
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
</style>
The first thing I thought about is to pass an index to change function, thus calculating some value independent of the v-for loop:
<td v-for="(date, index) in dayArr" :key="date.id">
<!-- pass index to change method -->
<button #click="change(index)" :id="index">+</button>
<modal-component #changevisibility="change(index)" v-if="modalToggled">
<!-- to slot pass the new variable -->
<!-- remember to add it to data() with some init value like null -->
<p>{{ currentDate }}</p>
</modal-component>
</td>
...
methods: {
change(index) {
// set currentDate value each time change method is being run
this.currentDate = this.dayArr[index];
this.modalToggled = !this.modalToggled
},
...
}
The reason for the issue you’ve experienced, is that v-for renders a list of items and sets the variables in a same way the code below does:
let x = 0;
for (i = 0; i < 10; i++) {
x = i;
}
console.log(x); // this will always console out x = 9
In contrary, event handling (like #click) makes a directive that listens to DOM events and runs a method each time the event is triggered. That’s at least how I understand it…

Iterating through html array is not working in javascript

I tried iterating through this but could not.
the function below
function orderpackage (){
var product_line = $('#carttable')[0].getElementsByTagName('tr');
for (var i = 1; i < product_line.length; i++) {
}
console.log(product_line)
Produces this in the console output
each of the tr.table_row is made from this
<tr class="table_row">
<td class="column-1">
<div class="how-itemcart1">
<img src=${Items.imageurl} alt="IMG">
</div>
</td>
<td class="column-2">${Items.name}</td>
<td class="column-3">$ ${Items.price}</td>
<td class="column-4">
<div class="wrap-num-product flex-w m-l-auto m-r-0">
<div class="btn-num-product-down cl8 hov-btn3 trans-04 flex-c-m qty-change" id="qty-change">
<i class="fs-16 zmdi zmdi-minus"></i>
</div>
<input class="mtext-104 cl3 txt-center num-product" type="number" name="num-product1" value=${Items.user_quantity}>
<div class="btn-num-product-up cl8 hov-btn3 trans-04 flex-c-m qty-change" id="qty-change">
<i class="fs-16 zmdi zmdi-plus"></i>
</div>
</div>
</td>
<td class="column-5">${line_total_sum}</td>
</tr>
what I want to do is iterate through each and get the price, quantity and line total.
When I tried the function below for the line total is shows error
var product_line = $('#carttable')[0].getElementsByTagName('tr')[4];
How do I iterate through each tr to the price, quantity and line total?
With plain JS, you can use HTMLTableElement.rows to get all the rows on the table.
Then you need to iterate over them, probably skipping the first one (header). For each one, access the children (cells) that contain the fields you need and create a new array with them, [price, quantity, total], and push that one to another array containing the data for all the table.
Here's one way to do it using Array.from() and Array.prototype.map():
const tableData = Array.from(document.getElementById('table').rows).slice(1).map(row => {
const cells = row.children;
return [cells[0].innerText, cells[1].innerText, cells[2].innerText];
});
console.log(JSON.stringify(tableData));
table {
border-collapse: collapse;
font-family: monospace;
text-align: right;
}
table, th, td {
border: 3px solid black;
}
th, td {
padding: 5px 10px;
}
<table id="table">
<tr><th>PRICE</th><th>QUANTITY</th><th>TOTAL</th></tr>
<tr><td>1</td><td>5</td><td>5</td></tr>
<tr><td>10</td><td>2</td><td>20</td></tr>
<tr><td>8</td><td>4</td><td>32</td></tr>
</table>
If you prefer to use a for...of loop instead:
let tableData = [];
// Iterate over every row:
for (const row of document.getElementById('table').rows) {
// Get the cells in the current row:
const cells = row.children;
// Read the text on the columns we want:
tableData.push([cells[0].innerText, cells[1].innerText, cells[2].innerText]);
}
// Remove the first row (header):
tableData = tableData.slice(1);
console.log(JSON.stringify(tableData));
table {
border-collapse: collapse;
font-family: monospace;
text-align: right;
}
table, th, td {
border: 3px solid black;
}
th, td {
padding: 5px 10px;
}
<table id="table">
<tr><th>PRICE</th><th>QUANTITY</th><th>TOTAL</th></tr>
<tr><td>1</td><td>5</td><td>5</td></tr>
<tr><td>10</td><td>2</td><td>20</td></tr>
<tr><td>8</td><td>4</td><td>32</td></tr>
</table>
Or just a normal for loop instead:
const rows = document.getElementById('table').rows;
const totalRows = rows.length;
const tableData = [];
// Iterate over every row, skipping the first one (header) already:
for (let i = 1; i < totalRows; ++i) {
// Get the cells in the current row:
const cells = rows[i].children;
// Read the text on the columns we want:
tableData.push([cells[0].innerText, cells[1].innerText, cells[2].innerText]);
}
console.log(JSON.stringify(tableData));
table {
border-collapse: collapse;
font-family: monospace;
text-align: right;
}
table, th, td {
border: 3px solid black;
}
th, td {
padding: 5px 10px;
}
<table id="table">
<tr><th>PRICE</th><th>QUANTITY</th><th>TOTAL</th></tr>
<tr><td>1</td><td>5</td><td>5</td></tr>
<tr><td>10</td><td>2</td><td>20</td></tr>
<tr><td>8</td><td>4</td><td>32</td></tr>
</table>

auto refrsh api data

i need to refresh particular data line in every interval when the value change
$(document).ready(
function() {
setInterval(function() {
var randomnumber = Math.floor();
$('#output').text(
gettxt()+ randomnumber);
}, 1000);
});
function gettxt(){
fetch('https://min-api.cryptocompare.com/data/top/exchanges?fsym=BTC&tsym=USD')
.then((res)=>res.text())
.then((data)=>{
document.getElementById('output').innerHTML=data;
})
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<div id="output" style="margin:5px 0;">
</div>
<script type="text/javascript"
src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
</body></html>
Here i get all refreshed in every seconds. i need to refresh only a particular line
Hi Here I done as per your req, Just one line I have done, for other line do by your self, I just makes your string obj into obj and added table style.
js fiddle
html
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
</style>
<div id="output" style="margin:5px 0;">
</div>
<table>
<tr>
<th style="margin-left:20px">exchange</th>
<th>fromSymbol</th>
<th>toSymbol</th>
<th> volume24h</th>
<th>volume24hTo</th>
</tr>
<tr>
<td>Bitfinex</td>
<td>BTC</td>
<td>USD</td>
<td id="volume24h">BTC</td>
<td id="volume24hTo">USD</td>
</tr>
</table>
java script
$(document).ready(
function() {
setInterval(function() {
var randomnumber = Math.floor();
$('#output').text(
gettxt()) + randomnumber;
}, 1000);
gettxt()
});
function gettxt(){
fetch('https://min-api.cryptocompare.com/data/top/exchanges?fsym=BTC&tsym=USD')
.then((res)=>res.text())
.then((data)=>{
var dataTemp = JSON.parse(data);
document.getElementById('volume24h').innerHTML=dataTemp.Data[0].volume24h;
document.getElementById('volume24hTo').innerHTML=dataTemp.Data[0].volume24hTo;
console.log(dataTemp);
})
}

Javascript sorting a csv rows and displaying in table

I have a csv file which has this format:
Major;2;4;29
Major should be displayed on the 4 row 2 column.
The file can have a lot nof rows!
I have created this:
var fileInput = document.getElementById("csv"),
readFile = function () {
var reader = new FileReader();
reader.onload = function () {
document.getElementById('out').innerHTML = reader.result;
};
reader.readAsBinaryString(fileInput.files[0]);
};
fileInput.addEventListener('change', readFile);
<style type="text/css">
output {
display: block;
margin-top: 4em;
font-family: monospace;
font-size: .8em;
}
</style>
which basically takes a csv file as an input and prints all as it is raw!How can I work and divide the rows on the ";"?And I also want an honest answer what level is this for?(intern,senior?)
Here's a trivial example, it's fairly straight forward. The issue will be splitting the data, it's pretty simple if the data is simple and the delimiter unique. But if the delimiter is in the data, the splitting into values requires a little more cleverness.
This uses table.rows to get the row, then row.cells to get the cell and inserts the value. Columns and rows are zero indexed, and for rows includes the header and footer (if they exist). You can also use the tbody.rows if the header rows should be skipped.
var data = 'Major;1;2;29\nMinor;2;3;29';
function insertData(id, data) {
// Show data
console.log(data);
// Get the table
var table = document.getElementById(id);
// Split the data into records
var dataRows = data.split(/\n/);
// Split each row into values and insert in table
if (table) {
dataRows.forEach(function(s) {
var x = s.split(';');
table.rows[x[2]].cells[x[1]].textContent = x[0];
});
}
}
table {
border-collapse: collapse;
border-left: 1px solid #999999;
border-top: 1px solid #999999;
}
td, th {
border-right: 1px solid #999999;
border-bottom: 1px solid #999999;
}
<table id="t0">
<thead>
<tr>
<th>col 0<th>col 1<th>col 2
</thead>
<tbody>
<tr>
<td> <td><td>
<tr>
<td> <td><td>
<tr>
<td> <td><td>
</tbody>
</table>
<button onclick="insertData('t0', data)">Insert data</button>

Conditionals in Handlebars.js when fetching data from Google Spreadsheet

Where I'm At
I'm using Tabletop.js and Handlebars.js to pull all the data from a Google Spreadsheet related to politician statements and then display them onto the page.
Problem
a) I'm having trouble fetching the data for validity from the console from a specific object. When I console.log(data), I'm able to get each of the objects from the Google Spreadsheet, but I haven't been able to get just validity from the first or third object for instance.
Console (single object)
Object {Facts: Tabletop.Model}
+-- Facts: Tabletop.Model
++-- column_names: Array[8]
++-- elements: Array[10]
+++-- 0: Object
+++-- citation1url: "Citation 1-1"
+++-- citation2url: "Citation 2-1"
+++-- citation3url: "Citation 3-1"
+++-- datesaid: "2/20/2015"
+++-- explanation: "Explanation 1"
+++-- name: "Politician 1"
+++-- rowNumber: 1
+++-- statement: "This is my first statement"
+++-- validity: "TRUE"
b) Having syntax issues, wondering if using conditionals in Handlebars would be most efficient way of changing the border color of an element if the validity of a statement (based off data from the spreadsheet) is true, false or unconfirmed vs. writing an if/statement and using jQuery's .css() or .addClass()?
Trying to do something like this (both aren't working)
if (validity == true) {
$(".container").css("border", "1px solid #2ECC40");
} else if (validity == unconfirmed) {
$(".container").css("border", "1px solid #FFDC00");
} else (validity == false) {
$(".container").css("border", "1px solid #FFDC00");
}
OR
{#if Facts.validity.TRUE }}
<div class="trueContainer container">
{{else if Facts.validity.FALSE}}
<div class="falseContainer container">
{{else Facts.validity.UNCONFIRMED}}
<div class="falseContainer container">
{{/if}}
Links
Google Spreadsheet: https://docs.google.com/spreadsheets/d/1glFIExkcuDvhyu5GPMaOesB2SlJNJrSPdBZQxxzMMc4/pubhtml
JSBin: http://jsbin.com/zomopeqoza/1/edit?html,css,output
Relevant Files
scripts (Currently inline)
<!-- This is where the template for facts goes -->
<script id="poli" type="text/x-handlebars-template">
<div class="container">
<p class="claim">Claim: {{name}} has said "{{statement}}"</p>
<p class="explanation">This statement is {{validity}}. This is reason number one and a detailed explanation. <sup class="unconfirmed">1</sup> This is reason number two with a detailed explanation. <sup class="unconfirmed">2</sup> And this is {{explanation}} <sup class="unconfirmed">3</sup> These fact checking boxes should always include 2-3 cited explanation, written by the reporter and linked to a file on DocumentCloud or Soundcloud.</p>
</div>
</script>
var public_spreadsheet_url = "https://docs.google.com/spreadsheets/d/1glFIExkcuDvhyu5GPMaOesB2SlJNJrSPdBZQxxzMMc4/pubhtml";
$(document).ready( function() {
Tabletop.init( { key: public_spreadsheet_url,
callback: showInfo,
parseNumbers: true } );
});
function showInfo(data, tabletop) {
var source = $("#poli").html();
var template = Handlebars.compile(source);
// The actual name of the sheet, not entire .csv
$.each( tabletop.sheets("Facts").all(), function(i, fact) {
var html = template(fact);
// You need an element with this id or class in your HTML
$("#poli-list").append(html);
console.log(data);
});
}
style.css
/*----------------------------------
MAIN STYLES
----------------------------------*/
.trueContainer {
border: 2px solid #2ECC40;
}
.falseContainer {
border: 2px solid #FF4136;
}
.unconfirmedContainer {
border: 2px solid #FFDC00;
}
.container {
margin-top: 1%;
padding: 0.5%;
width: 50%;
}
.claim, sup {
font-family: 'Lato', sans-serif;
font-weight: 900;
}
sup {
padding: 2px;
}
a {
text-decoration: none;
}
.explanation {
font-family: 'Lato', sans-serif;
font-weight: 400;
line-height: 28px;
letter-spacing: 0.025px;
}
.true {
color: #2ECC40;
}
.false {
color: #FF4136
}
.unconfirmed {
color: #FFDC00;
}

Categories