How to convert a html button into native script? - vue.js

This is the html code, this button is used to filter food by name:
So the name of the food should be displayed as a button so that users can filter the option.
<button id="filterme" v-for="f in filterFood"
#click="$chooseFilter(f)">Filter food by {{f}}</button>
This is the script code:
const app = new Vue({
el: "#app",
data: {
thisFood: [], //food array
newFood: {
name: "",
price: "",
cuisine: ""
},
filterFood: ["null", "pizza", "chips", "rice", "chocolate", "salad"]
methods() {
if (localStorage.getItem("thisFood")) {
try {
this.thisFood= JSON.parse(localStorage.getItem("thisFood"));
} catch (e) {
localStorage.removeItem("newFood");
}
this.thisFood.push(this.newFood); //add new food
this.newFood= {
name: "",
price: "",
cuisine: "",
}
}
},
chooseFilter(filter) {
this.filter = filter;
},
I tried using a button it's not working.
<button text:"filterme" for =" f in filterFood" #tap="chooseFilter(f)">
Filter food by {{f}} </button>

Please take another look at the Vue documentation: https://v2.vuejs.org/v2/guide/components.html
Maybe you're not sharing all your code, but the structure is way off.
Your methods function (which should be an object) is inside your data object.
Besides that you're missing parentheses .
Start with a valid structure and syntax:
const app = new Vue({
el: "#app",
data: {
thisFood: [], //food array
newFood: {
name: "",
price: "",
cuisine: "",
},
filterFood: ["null", "pizza", "chips", "rice", "chocolate", "salad"]
},
methods: {
chooseFilter(filter) {
//
}
},
});

Related

Vue.js access variable from method

I try to fetch stocks data from an API. This data should be used to create a chart.js graph.
how do I access in vue.js data to generate a chart.js line chart from the methods http(axios) call?
Is it possible to access the data directly in the mounted component or should I define a const in the section and create the variables there?
<template>
<select v-model="selected">
<option v-for="option in options" :value="option.value">
{{ option.text }}
</option>
</select>
<div>Selected: {{ selected }}</div>
<div>
<canvas id="myChart" height="200" width="650"></canvas>
</div>
<script>
export default {
mounted() {
const ctx = document.getElementById("myChart");
const myChart = new Chart(ctx, {
type: "line",
data: {
labels: [prices[0].date],
datasets: [
{
label: 'Dataset msft',
data: prices[0].price
},
{
label: 'Dataset google',
data: prices[1].price
},
],
},
});
},
data() {
return {
selected: "",
prices: [],
options: [
{ text: "msft", value: "msft" },
{ text: "GOOGL", value: "GOOGL" },
],
};
},
watch: {
selected: function () {
this.getPrice();
},
},
methods: {
getPrice: function () {
var this_ = this;
axios
.get(
"https://site/...."
)
.then((response) => {
// JSON responses are automatically parsed.
this_.prices = response.data;
})
},
},
};
</script>
Yes, you can access variables in data() from mounted().
You need to prepend variables with this. when using the Options API
ex: this.prices[0].price
As you are putting watcher on selected but I did not see any changes in the selected variable in your code. As per my understanding you are making an API call to get the graph data based on the selected option.
If Yes, Instead of generating a chart in mounted you can generate it inside your getPrice() method itself based on the response. It should be :
methods: {
getPrice: function () {
var this_ = this;
axios
.get(
"https://site/...."
)
.then((response) => {
this.generateChart(response.data);
})
},
generateChart(prices) {
const ctx = document.getElementById("myChart");
const myChart = new Chart(ctx, {
type: "line",
data: {
labels: [prices[0].date],
datasets: [
{
label: 'Dataset msft',
data: prices[0].price
},
{
label: 'Dataset google',
data: prices[1].price
}
]
}
});
}
}
Here, a very basic example:
<script>
export default {
async mounted() {
await this.$nextTick();
const ctx = document.getElementById("myChart");
this.chart = new Chart(ctx, {
type: "line",
data: {
labels: [],
datasets: [],
},
});
},
data() {
return {
selected: "",
chart: null,
options: [
{ text: "msft", value: "msft" },
{ text: "GOOGL", value: "GOOGL" },
],
};
},
watch: {
selected: function () {
this.getPrice();
},
},
methods: {
async getPrice() {
let { data } = await axios.get("https://site/....");
this.chart.data.datasets = [{ label: "dummy data" , data: [2, 3, 4]}];
this.chart.data.label = [1, 2, 3];
this.chart.update(); //very important, always update it
},
},
};
</script>
You create a property called chart and save your chart to it.
Then, after you fetch your data, you can access your chart with this.chart and then you set your datasets and labels. Whenever you make an change to the chart, use this.chart.update() to update it on the browser.
If you execute this code, you should see some dummy data in the chart

How to group letters of alphabet and render to template in vue

I have a vuejs data like this:
new Vue({
el: "#app",
data() {
return {
alpha: [{
artist: "Aa"
}, {
artist: "Az"
},
{
artist: "Ab"
},
{
artist: "Ba"
},
{
artist: "Bb"
},
{
artist: "Bc"
},
{
artist: "Da"
},
{
artist: "Db"
}, {
artist: "Dc"
}, {
artist: "Dx"
},
]
}
}
})
What I want to do is simple to take the first letters of artist: A, B, C, D and create an array from them. After that I want to group all the artists by their index. So, the output would be:
A: (3) ["Aa", "Az", "Ab"]
B: (3) ["Ba", "Bb", "Bc"]
D: (4) ["Da", "Db", "Dc", "Dx"]
I can do this in my code, see below but the template isn't rendering it.
Here is the fiddle https://jsfiddle.net/fcas1wke/ for that works, you can see the console for the output
The array doesn't render because you are using non-numeric indexes on your array. This is described in more detail here, but basically non-numeric indexes can't be iterated over so they won't appear in the output.
A more standard way to handle this would be to use an object instead of an array. Here's a working version of your component:
Vue.component("alphabets", {
props: ['data'],
computed: {
stack() {
const result = {};
this.data.forEach(function(element) {
if (Array.isArray(result[element.artist[0]])) {
result[element.artist[0]].push(element.artist);
} else {
result[element.artist[0]] = [element.artist];
}
});
return result;
},
},
template: `<div>{{ stack }}</div>`,
});
Note this version uses a computed property instead of modifying the component's state on created.

SortableJS Drag into empty Vuetify v-data-table not working

I'm trying to create a drag-drop between two v-data-tables in Vuetify using SortableJS.
Here is an example with 3 tables: https://codepen.io/arno-van-oordt/pen/MdqrgK
It works fine if both tables start with at least one item (between table 1 and 3 for example). But when a table starts of empty I can't seem to drop items onto it.
What would be the best solution to this issue?
new Vue({
el: "#app",
data() {
return {
headers: [
{
text: "Title",
value: "name"
}
],
list1: [
{
name: "Item1-1"
},
{
name: "Item1-2"
}
],
list2: [],
list3: [
{
name: "Item3-1"
},
{
name: "Item3-2"
}
]
};
},
mounted: function() {
new Sortable(this.$refs.table1.$el.getElementsByTagName("tbody")[0], {
group: "test",
draggable: ".sortableRow"
});
new Sortable(this.$refs.table2.$el.getElementsByTagName("tbody")[0], {
group: "test",
draggable: ".sortableRow"
});
new Sortable(this.$refs.table3.$el.getElementsByTagName("tbody")[0], {
group: "test",
draggable: ".sortableRow"
});
},
methods: {}
});
This was a flaw in SortableJS which is now solved in the next-version branch.
This branch is still in development but is backwards compatible and will be merged to the master branch soon.
Edit: It is now in the master branch

How can I filter the ${{ data }} object to only show specific values?

I am using vue.js and dumping my data ${{ data }} and outputing this to the user, however, I would only like to display specific values. In this instance, I want to show everything but NOT Actions.
I would only like to show: Name, Description and Method.
{
"Name": "",
"Description": "",
"Actions": [
{
"Actions": "Microsoft.AAD/domainServices/oucontainer/write"
},
{
"Actions": "Microsoft.AAD/domainServices/oucontainer/delete"
},
{
"Actions": "Microsoft.AAD/domainServices/oucontainer/read"
}
],
"Method": "a,b,c,d,"
}
You can create a method which will do it for you.
let first create a method where I will be using spread syntax.Check this link as well.
https://codingexplained.com/coding/front-end/vue-js/working-with-methods-in-vue-js
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!',
actions : ["this i it", "abc"],
lovely: "asdf"
},
methods : {
getData : function(){
let {actions, ...dataExceptAction} = this.$data;
return dataExceptAction;
}
}
})
Now I can simply use the getData method on my template
<div id="app">
<p>{{ getData() }}</p>
</div>
Working example of this is here
https://jsfiddle.net/3cy2roLp/45/

Vuejs - list - How to pass click functions as string

I have an array of objects, each with a click property (a string) that is passed to a click-event handler. I can print the .click property to the console, but it is not recognized as Vue data. I tried to eval(todo.click), but it didn't work.
html:
<div id="app">
<h2>Todos:</h2>
<ol>
<li v-for="todo in todos">
<label #click="clickMethod(todo)">{{todo.text}}</label>
</li>
</ol>
<br>
<div v-if="infoVisible">infoVisible</div>
<div v-if="tresVisible">tresVisible</div>
</div>
and my js:
new Vue({
el: "#app",
data: {
infoVisible:false,
tresVisible:true,
todos: [
{ text: "Learn JavaScript", done: false, click:'infoVisible=!infoVisible' },
{ text: "Learn Vue", done: false, click:'infoVisible=!infoVisible' },
{ text: "Play around in JSFiddle", done: true , click:'infoVisible=!infoVisible'},
{ text: "Build something awesome", done: true , click:'tresVisible=!tresVisible'}
]
},
methods: {
clickMethod(todo){
console.log(todo.click)
todo.click()
}
}
})
Fiddle
Instead of using strings as functions (which would require eval()), you could define function expressions:
new Vue({
el: "#app",
data: (vm) => ({
infoVisible: false,
tresVisible: true,
todos: [
{ ..., click() { vm.infoVisible = !vm.infoVisible } },
{ ..., click() { vm.infoVisible = !vm.infoVisible } },
{ ..., click() { vm.infoVisible = !vm.infoVisible } },
{ ..., click() { vm.tresVisible = !vm.tresVisible } },
]
}),
methods: {
clickMethod(todo){
todo.click()
}
}
})
Steps:
In todos[], change the type of .click properties from strings to function expressions:
//click: 'infoVisible = !infoVisible' // from strings
click() { infoVisible = !infoVisible } // to function expressions (to be updated in step 3)
In the function body, a reference to the Vue instance is required so that click() can change the data properties (i.e., infoVisible and tresVisible). Update the Vue declaration's data property to be a function that takes an argument (the argument will be the Vue instance itself):
data: (vm) => ({/* ... */})
Update click() to use that argument to reference the target data properties:
click() { vm.infoVisible = !vm.infoVisible }
^^^ ^^^
updated fiddle
eval(todo.click) will work but you need to add "this." to all of the todo properties in the click attributes so they have the right context, that is the context of the Vue instance.
new Vue({
el: "#app",
data: {
infoVisible:false,
tresVisible:true,
todos: [
{ text: "Learn JavaScript", done: false, click:'this.infoVisible=!this.infoVisible' },
{ text: "Learn Vue", done: false, click:'this.infoVisible=!this.infoVisible' },
{ text: "Play around in JSFiddle", done: true , click:'this.infoVisible=!this.infoVisible'},
{ text: "Build something awesome", done: true , click:'this.tresVisible=!this.tresVisible'},
]
},
methods: {
clickMethod(todo){
eval(todo.click)
}
}
})