VueJS date piker Vuetify listener - vue.js

I need your help to solve a problem I am facing.
I am currently working with a computed on Vue.js, however I want to use a listener instead of this computed.
Do you know how I can switch from one to the other?
Thank you in advance.
import { MUTATION_entreePlanningCreate } from "./graphql/mutations";
export default {
name: "EntreePlanningForm",
data: function () {
return {
dates: ["", ""],
datesRules: [(v) => !!v || "Veuillez selectionner une date"],
label: "",
labelRules: [
(v) => v.length < 20 || "Le champ doit comporter moin de 20 caractère",
],
description: "",
};
},
methods: {
envoyer: function () {
if (this.$refs.form.validate()) {
this.$apollo
.mutate({
mutation: MUTATION_entreePlanningCreate,
variables: {
input: this.input,
},
})
.then((data) => {
console.log(data);
});
}
},
},
computed: {
input() {
return {
dateDebut: this.dates[0],
dateFin: this.dates[1],
label: "",
description: "",
};
},
},
};

Related

How do I seperate an array so the data shows up as individual list items?

I am struggling re-writing some older code I made in vue. I have a form which allows the user to enter multiple email recipients. The problem is that the array in which these emails are stored outputs them as one single item.
How do I seperate these email addresses?
This is my code. I know that Vue has something called Split, but I am not sure where I could use it here (or if it would change anything).
<template>
<b-form-group :label="label">
<vue-tags-input
v-model="inputValue"
:tags="tags"
:autocomplete-min-length="0"
:add-on-key="[',', 13]"
:autocomplete-items="filteredAutocompleteItems"
:placeholder="$t('addEmailAddressesHere')"
data-test-id="send-doc-email-to"
#before-adding-tag="addTag"
#tags-changed="tagsChanged"
class="mw-100"
/>
</b-form-group>
</template>
<script>
import {propertyService} from '#/services/property';
import {tenancyService} from '#/services/tenancy';
import {unitService} from '#/services/unit';
import {userService} from '#/services/user';
import VueTagsInput from '#johmun/vue-tags-input';
export default {
components: {
VueTagsInput
},
props: {
value: Array,
label: String,
entityId: String,
entityType: String,
prefill: {
type: Boolean,
default: false
},
asNotification: {
type: Boolean,
default: false
},
includeUser: {
type: Boolean,
default: false
}
},
data() {
return {
inputValue: '',
autocompleteItems: []
};
},
computed: {
tags() {
return (this.value || []).map(this.setText);
},
filteredAutocompleteItems() {
return this.autocompleteItems.filter(autocompleteItem =>
autocompleteItem.text.toUpperCase().includes(this.inputValue.toUpperCase()));
}
},
methods: {
addTag({tag, addTag}) {
if (!tag.recipients) {
tag.recipients = [{emailAddress: tag.text}];
}
addTag(tag);
},
setText(tag) {
tag.text = [tag.description, tag.recipients.map(recipient => recipient.emailAddress).join(', ')].filter(Boolean).join(' | ');
return tag;
},
tagsChanged(newTags) {
this.$emit('input', newTags);
},
load() {
switch (this.entityType) {
case 'TENANCY':
userService.getCurrentUser().then(userResult => {
tenancyService.getTenants(this.entityId).then(result => {
const defaultTags = [];
const recipients = result.data
.map(tenant => tenant.legalEntity)
.filter(legalEntity => legalEntity.email || (!legalEntity.email && this.asNotification ? legalEntity.name : null))
.map(legalEntity => ({
emailAddress: legalEntity.email || (!legalEntity.email && this.asNotification ? legalEntity.name.concat(' ', `(${this.$t('letterMail').toLowerCase()})`) : null),
legalEntityId: legalEntity.id
}));
if (recipients.length) {
defaultTags.push(this.setText({description: this.$t('tenants'), recipients}));
}
this.autocompleteItems.push(...defaultTags);
if (this.includeUser) {
defaultTags.push(this.setText({
description: this.$t('user'),
recipients: [{emailAddress: userResult.data.email}]
}));
}
if (this.prefill) {
this.tagsChanged(defaultTags);
}
tenancyService.getUnits(this.entityId).then(result =>
result.data.forEach(unitTenancy => this.addPropertyContactsToAutocompleteItems(unitTenancy.unit.propertyId)));
});
});
break;
case 'UNIT':
unitService.get(this.entityId).then(result =>
this.addPropertyContactsToAutocompleteItems(result.data.propertyId));
break;
case 'PROPERTY':
this.addPropertyContactsToAutocompleteItems(this.entityId);
break;
}
},
addPropertyContactsToAutocompleteItems(propertyId) {
propertyService.listContacts(propertyId).then(result => {
this.autocompleteItems.push(...result.data
.filter(contact => contact.email)
.map(contact => this.setText({
description: contact.profession ? this.$t(`model.contact.professions.${contact.profession}`) : null,
recipients: [{emailAddress: contact.email, legalEntityId: contact.id}]
}))
);
});
}
},
created() {
this.load();
}
};
</script>

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

Apexchats.js axios gives me undefined with Vue

I am trying to get data from server using vue and apexcharts, but even after I called data with axios, it gives me undefined..
What have I missed?
template
<apexchart
ref="chart1"
width="100%"
:options="chartOptions" :series="series">
</apexchart>
data from url
{
"pageviews": 1313,
"new_users": 1014
}
script
export default {
data: function () {
return {
series: [],
chartOptions: {
chart: {
type: 'donut',
},
colors: ['#01cd49', '#007568'],
labels: ['new', 're'],
}
},
created: function () {
this.getByVisitor()
},
methods: {
getByVisitor() {
const url = 'url';
axios
.get(url)
.then(response => {
this.$refs.chart1.updateSeries([{
name: 'Sales',
data: response.data
}])
})
.catch(error => (this.byVisitor = error.data));
console.log(`---------------this.$refs.chart1`, this.$refs.chart1);
},
}
See Updating Vue Chart Data
There's no need to directly call the updateSeries() method on the chart component since it is able to react to changes in series. All you have to do is update your series data property
export default {
data: () => ({
series: [], // 👈 start with an empty array here
byVisitor: null, // 👈 you seem to have missed this one for your error data
chartOptions: {
chart: {
type: 'donut',
},
colors: ['#01cd49', '#007568'],
labels: ['new', 're'],
}
}),
created: function() {
this.getByVisitor()
},
methods: {
async getByVisitor() {
const url = 'url';
try {
const { data } = await axios.get(url)
// now update "series"
this.series = [{
name: "Sales",
data
}]
} catch (error) {
this.byVisitor = error.data
}
},
}
}

Get data in ag-grid

I was able to pull data into the database with bootstrap-vue.
I need to transfer to ag-grid, but I don't know how to do it
Someone help-me, this is code in ag-grid:
<template v-if="instituicao">
<div>
<button #click="getSelectedRows()">Get Selected Rows</button>
<ag-grid-vue style="width: 1000px; height: 500px;"
class="ag-theme-balham"
v-model="instituicao.codigo" required
:floatingFilter="true"
:gridReady="onGridReady"
:enableColResize="true"
:columnDefs="columnDefs"
:rowData="rowData"
:enableSorting="true"
:enableFilter="true">
</ag-grid-vue>
</div>
</template>
<script>
import PageTitle from '../template/PageTitle'
import axios from 'axios'
import { baseApiUrl, showError } from '#/global'
import { AgGridVue } from "ag-grid-vue"
import { transformHeader, transformRows } from '../../lib/grid.js'
/* import "ag-grid-enterprise" */
export default {
name: 'InstituicaoAdmin',
components: { AgGridVue, PageTitle },
data() {
return {
columnDefs: null,
rowData: null,
mode: 'save',
instituicao: {},
instituicoes: [],
fields: [
{ key: 'id', label: 'Id', sortable: true },
{ key: 'name', label: 'Name', sortable: true }
],
}
},
methods: {
onGridReady(params) {
this.gridApi = params.api;
this.columnApi = params.columnApi;
this.gridApi.setHeaderHeight(50);
},
sizeToFit() {
this.gridApi.sizeColumnsToFit();
// this.autosizeHeaders();
},
autoSizeAll() {
var allColumnIds = [];
this.columnApi.getAllColumns().forEach(function(column) {
allColumnIds.push(column.colId);
});
this.columnApi.autoSizeColumns(allColumnIds);
},
getSelectedRows() {
const selectedNodes = this.gridApi.getSelectedNodes();
const selectedData = selectedNodes.map(node => node.data);
const selectedDataStringPresentation = selectedData.map(node => node.make + ' ' + node.model).join(', ');
alert(`Selected nodes: ${selectedDataStringPresentation}`);
},
loadInstituicoes() {
const url = `${baseApiUrl}/instituicao`
axios.get(url).then(res => {
this.instituicoes = res.data
})
},
reset() {
this.mode = 'save'
this.instituicao = {}
this.loadInstituicoes()
},
save() {
const method = this.instituicao.id ? 'put' : 'post'
const id = this.instituicao.id ? `/${this.instituicao.id}` : ''
axios[method](`${baseApiUrl}/instituicao${id}`, this.instituicao)
.then(() => {
this.$toasted.global.defaultSuccess()
this.reset()
})
.catch(showError)
},
remove() {
const id = this.instituicao.id
axios.delete(`${baseApiUrl}/instituicao/${id}`)
.then(() => {
this.$toasted.global.defaultSuccess()
this.reset()
})
.catch(showError)
},
loadInstituicao(instituicao, mode = 'save') {
this.mode = mode
this.instituicao = { ...instituicao }
}
},
beforeMount() {
this.columnDefs = [
{headerName: 'Id', field: 'id', sortable: true },
{headerName: 'Name', field: 'name', sortable: true, filter: true },
{headerName: 'Price', field: 'price', sortable: true, filter: true }
];
fetch('https://api.myjson.com/bins/15psn9')
.then(result => result.json())
.then(rowData => this.rowData = rowData);
},
computed: {
columnDefs() {
return transformHeader(this.payload.header);
},
rowData() {
return transformRows(this.payload.data.rows, this.columnDefs);
}
},
mounted() {
this.loadInstituicoes()
}
}
</script>
<style>
#import "../../../node_modules/ag-grid/dist/styles/ag-grid.css";
#import "../../../node_modules/ag-grid/dist/styles/ag-theme-balham.css";
</style>
My question is how can I do the GET, PUT, POST, and DELETE operations using the ag-grid framework.
Usando o bootstrap-vue, eu poderia executar ou obter o banco de dados através da propriedade "fields".
<script>
import PageTitle from '../template/PageTitle'
import axios from 'axios'
import { baseApiUrl, showError } from '#/global'
export default {
name: 'InstituicaoAdmin',
components: { PageTitle },
data: function() {
return {
mode: 'save',
instituicao: {},
instituicoes: [],
fields: [
{ key: 'id', label: 'Id', sortable: true },
{ key: 'name', label: 'Name', sortable: true }
]
}
},
methods: {
loadInstituicoes() {
const url = `${baseApiUrl}/instituicao`
axios.get(url).then(res => {
this.instituicoes = res.data
})
},
reset() {
this.mode = 'save'
this.instituicao = {}
this.loadInstituicoes()
},
save() {
const method = this.instituicao.id ? 'put' : 'post'
const id = this.instituicao.id ? `/${this.instituicao.id}` : ''
axios[method](`${baseApiUrl}/instituicao${id}`, this.instituicao)
.then(() => {
this.$toasted.global.defaultSuccess()
this.reset()
})
.catch(showError)
},
remove() {
const id = this.instituicao.id
axios.delete(`${baseApiUrl}/instituicao/${id}`)
.then(() => {
this.$toasted.global.defaultSuccess()
this.reset()
})
.catch(showError)
},
loadInstituicao(instituicao, mode = 'save') {
this.mode = mode
this.instituicao = { ...instituicao }
}
},
mounted() {
this.loadInstituicoes()
}
}
</script>
I was able to solve the problem using axios using destructuring:
beforeMount() {
this.columnDefs = [
{headerName: 'Id', field: 'id', editable: true},
{headerName: 'Name', field: 'name', editable: true}
];
axios.get(`${baseApiUrl}/instituicao`)
.then(({data}) => this.rowData = data)
},

How to reference a parent prop value in a vue-i18n translation string?

I am trying to make a vuetify text field reusable and would like to pass some prop data from a parent component into the validation translation strings as a variable. This prop is a max. character value for validation.
Is it possible to insert a prop or data value into a translation string ? Something like ...
props: {
maxLength: { type: Number, default: 20 },
}
i18n: {messages: {
en: { name_length: "Max. {this.maxLength} characters" },...
}
I've tried:
"Max." + String(this.maxLength) + characters", but it comes out as undefined.
Here's the complete code for reference:
<template>
<v-text-field
v-model="text" :prepend-icon="iconfront"
:rules="nameRules" :name="name"
:label="label" :type="type">
</v-text-field>
</template>
<script>
export default {
props: {
value: {type: String},
iconfront: { type: String },
name: { type: String },
label: { type: String },
type: { type: String, default: 'text' },
minLength: { type: Number, default: 1 },
maxLength: { type: Number, default: 20 },
},
computed: {
text: { get() { return this.value },
set(val) { this.$emit('input', val) }
}
},
data () {
return {
nameRules: [
(v) => !!v || this.$i18n.t("name_rule"),
(v) => v && v.length <= this.maxLength || this.$i18n.t("name_length")
]
}
},
methods: {
onInput(input){
this.$emit('textFieldInput', input)
}
},
i18n: {
messages: {
en: {
name_rule: "required field",
**name_length: "Max. {this.maxLength} characters",**
confirmation_rule: "passwords must match",
email_rule: "email must be valid",
password_length: "Length must be" + String(this.minLength)+ "-" + String(this.minLength) + "characters",
},
de: {
name_rule: "Pflichtfeld",
name_length: "Max. 20 Zeichen",
confirmation_rule: "Passwörter müssen übereinstimmen",
email_rule: "Email muss gültig sein",
password_length: "Länge: 6-20 Zeichen",
},
fr: {
name_rule: "champs requis",
name_length: "20 caractères maximum",
confirmation_rule: "les mots de passe doivent correspondre",
email_rule: "email doit être valide",
password_length: "longueur requise: 6 à 20 caractères",
},
}
}, //end of translations
}
</script>
OK, found the answer after a bit of digging:
props: {
maxLength: { type: Number, default: 20 },
}
i18n: {messages: {
en: { name_length: "Max. {max} characters" },...
}
Then in the template, you can pass the prop into the translation:
$t("name_length", {max: this.maxLength})