link1918 link1919 link1920 link1921 link1922 link1923 link1924 link1925 link1926 link1927 link1928 link1929 link1930 link1931 link1932 link1933 link1934 link1935 link1936 link1937 link1938 link1939 link1940 link1941 link1942 link1943 link1944 link1945 link1946 link1947 link1948 link1949 link1950 link1951 link1952 link1953 link1954 link1955 link1956 link1957 link1958 link1959 link1960 link1961 link1962 link1963 link1964 link1965 link1966 link1967 link1968 link1969 link1970 link1971 link1972 link1973 link1974 link1975 link1976 link1977 link1978 link1979 link1980 link1981 link1982 link1983 link1984 link1985 link1986 link1987 link1988 link1989 link1990 link1991 link1992 link1993 link1994 link1995 link1996 link1997 link1998 link1999 link2000 link2001 link2002 link2003 link2004 link2005 link2006 link2007 link2008 link2009 link2010 link2011 link2012 link2013 link2014 link2015 link2016 link2017 link2018 link2019 link2020 link2021 link2022 link2023 link2024 link2025 link2026 link2027 link2028 link2029 link2030 link2031 link2032 link2033 link2034 link2035 link2036 link2037 link2038 link2039 link2040 link2041 link2042 link2043 link2044 link2045 link2046 link2047 link2048 link2049 link2050 link2051 link2052 link2053 link2054

[Vue.js] Vuex - Run function after multiple dispatches

I’m creating an application and at a certain point I need to load some data, but for the user not to see broken data I’m inserting a loading component.

Currently I put a setTimeout in the load, but at some point the API response can take more than 1 second. So I would like to update the loading state only when all the dispatches become completed.

MainComponent.vue

beforeCreate() {
this.$store.dispatch(‘responsibles/fetchData’)
this.$store.dispatch(‘events/fetchData’)
this.$store.dispatch(‘wallets/fetchData’)

// Need to run this setTimeout after all the above dispatches become completed…
setTimeout(() => {
this.loading = false
}, 1000)
}

store/modules/responsibles.js

const state = {
responsibles: []
}

const actions = {
fetchData({dispatch}) {
function getresponsibles() {
return http.get(‘responsibles’)
}

axios.all([
getresponsibles()
]).then(axios.spread(function (responsibles) {
dispatch(‘setResponsibles’, responsibles.data.data)
})).catch(error => console.error(error))
},
setResponsibles({commit}, responsibles) {
commit(‘SET_RESPONSIBLES’, responsibles)
}
}

const mutations = {
SET_RESPONSIBLES(state, responsibles) {
state.responsibles = responsibles
}
}

store/modules/events.js

const state = {
events: []
}

const actions = {
fetchData({dispatch}) {
function getEvents() {
return http.get(‘events’)
}

axios.all([
getEvents()
]).then(axios.spread(function (events) {
dispatch(‘setEvents’, events.data.data)
})).catch(error => console.error(error))
},
setEvents({commit}, events) {
commit(‘SET_EVENTS’, events)
}
}

const mutations = {
SET_EVENTS(state, events) {
state.events = events
}
}

store/modules/wallets.js

const state = {
wallets: []
}

const actions = {
fetchData({dispatch}) {
function getWallets() {
return http.get(‘wallets’)
}

axios.all([
getWallets()
]).then(axios.spread(function (wallets) {
dispatch(‘setWallets’, wallets.data.data)
})).catch(error => console.error(error))
},
setWallets({commit}, wallets) {
commit(‘SET_WALLETS’, wallets)
}
}

const mutations = {
SET_WALLETS(state, wallets) {
state.wallets = wallets
}
}

Solution :

Have the actions return the Promise created by Axios, eg

return axios.all(…

See https://vuex.vuejs.org/guide/actions.html#composing-actions
Wrap the dispatch calls in Promise.all and wait for them all to complete

Promise.all([
this.$store.dispatch(‘responsibles/fetchData’),
this.$store.dispatch(‘events/fetchData’),
this.$store.dispatch(‘wallets/fetchData’)
]).finally(() => {
// using “finally” so even if there are errors, it stops “loading”
this.loading = false
})

[Vue.js] Vue.js - Is it possible to use Javascript Dynamic Imports to load components from another server?ContextMy idea

Context

there is to create a Vue.js application as the UI of my REST API Back-end.
It will be displayed for every client.

This application displays a list of items to be handled (with a small workflow: open, in progress, done).

Some of my clients request a specific and different view for this list: they want, for instance, that the list is displayed in another layout, or with extra data from their internal applications.

My idea

So, there is to create specific Vue.js components for these clients, but I don’t want to “pollute” my main application code base with all the components for these clients.
that these views are handled in a specifically dedicated code base.

I was wondering if I could use Dynamic imports / Async components (Article on optimization with Dynamic imports and Official Vue.js doc for Dynamic imports) to load these components, based on the client that uses the application.
These components would be loaded from another server, not the server that serves the main Vue.js application.

The actual way of dynamically loading a component is:

‘my-component’: () => import(‘./my-async-component’)

Would it be possible to do something like:

‘my-component’: () => import(‘http://myspecificclient.mydomain.com/my-async-component')

I understand that dynamic loading is related in particular with Webpack and that it could be an issue here, but I’m not skilled enough in Webpack to know if what I would like to do is relevant.

Solution :

You may be able to use ajax…

var xhr = new XMLHttpRequest;

xhr.open(‘GET’, ‘[the url here]‘, true)

But I’m not really sure since you said you wanted to import it from another server

[Vue.js] Preserve scroll position on DOM update in vue.js

there is a chat application which loads the recent chat messages and store them in messages array. Previous chat history is loaded on scroll and will be added to the beginning of messages array. I need to preserve the scroll position when history is loaded

//chat.vue
<div ref=”chatHistory” @scroll=”fetchHistory”>
<div v-for=”item in messages” :key=”item.id”>
<span>{item.body}</span>
</div>
</div>

In fetchHistory method, I add the old messages to beginning of messages array

fetchHistory(){
if(this.$refs.messageHistory.scrollTop == 0){
var vm = this
this.currentPage.prevPage().then(paginator => {
vm.messages.unshift(…paginator.messages)
});
}
}

Solution :

Subtract initial height from final height in nextTick() function and update scroll position

fetchHistory(){
if(this.$refs.messageHistory.scrollTop == 0){
var initialHeight = this.$refs.messageHistory.scrollHeight
var vm = this
this.currentPage.prevPage().then(paginator => {
vm.messages.unshift(…paginator.messages)
vm.$nextTick(() => {
vm.$refs.messageHistory.scrollTop = vm.$refs.messageHistory.scrollHeight - initialHeight
})
});
}
}

[Vue.js] vue.js Where to put regularly repeating background query

I would like to query an API service every 15 seconds, so I can get data from a database and check whether something was changed. If there was a change, then my front end would update automatically because of how vue.js works.

while (true) {
setTimeout(function() {
QueryService.orders().then(response =>
this.orders = response.data
)
}, 15000)
}

My questions are:

Is this a good approach to solve such a problem at all?
What would be the best position in the code to place such a loop?

EDIT:

Using setInterval() seems to be the right way, but using a polling function with setInterval in the created() hook doesn’t affect the data-table at all. It shows me “No data available”:

data () {
return {
headers [
{ … },
{ … }
],
orders: []
}

created () {
setInterval(function() {
QueryService.orders().then(response => this.orders = response.data)
}, 15000)
}

Using the polling function without setInterval works and fills my data-table with data as usual:

created () {
QueryService.orders().then(response => this.orders = response.data)
}

Solution :

For a simple and quick solution, I’d go with I’mOnlyVueman’s answer. Here some example code I found from Vue.js polling using setINterval(). This example includes

pollData method initiated on created that dispatches a store action (which would call the API)
Canceling the poll as you navigate to another page using beforeDestroy

Code

data () {
return {
polling: null
}
},
methods: {
pollData () {
this.polling = setInterval(() => {
this.$store.dispatch(‘RETRIEVE_DATA_FROM_BACKEND’)
}, 3000)
}
},
beforeDestroy () {
clearInterval(this.polling)
},
created () {
this.pollData()
}

But polling an API isn’t very elegant and it doesn’t scale well. You’ll likely need to do something with Websockets, setting up the app to listen for events pushed from the API.

Here’s info on Subscriptions in Vue-Apollo & GraphQL that Denis Tsoi mentioned.

Subscriptions are a GraphQL feature that allows the server to send
data to the clients when a specific event happens on the backend.
Subscriptions are usually implemented with WebSockets, where the
server holds a steady connection to the client. That is, the
Request-Response-Cycle that we used for all previous interactions with
the API is not used for subscriptions. Instead, the client initially
opens up a steady connection to the server by specifying which event
it is interested in. Every time this particular event happens, the
server uses the connection to push the data thats related to the
event to the client.

Solution 2:

A loop like this would go in the component’s script within a mounted () lifecycle hook.

That would mean once the component loads the loop would trigger. For detailed guidance on this technique the vue.js docs are a good first stop, as well as this article.

[Vue.js] vue cli3 enable CORS

there is had this problem for nearly 2 days, any help would be a life saver.

there is my vue.js app running on 8080 dev mode and when trying to integrate blockstack login and that app tries to read http://localhost/manifest.json, so I placed it in static directory, but it is throwing me cors error, do we have solution for that vue.js cli configurations like vue.config.js?

Solution :

A CORS error means that you are trying to retrieve something from a domain that is not origin of where the request comes from. If the app runs on port 8080, you would expect it to try to retrieve the manifest.json file from localhost:8080/manifest.json, not localhost/manifest.json. It sounds like you may have hardcoded this hostname somehow without the port. Consider using urls relative to the main root (e.g. /manifest.json).

In any case, CORS errors can only be solved by matching the source domain and the target domain, or by having the server return the proper Access-Control-Allow-Origin header. Vue, as the frontend, cannot do much about that.

[Vue.js] vue.js change the values of a table in a reactive way

To create a table when using vuetify data-table. The data is coming from an express server which is requested via axios and then gives me a response that is structured as follows:

[
{
datetime: 123456789,
order: “abc100”,
status: “ok”
},
{
datetime: 123456789,
order: “abc200”,
status: “ok”
},

]

This response is being used by the vue.js front as follows:

<v-data-table
:headers=”headers”
:items=”orders”
\>
<template slot=”items” slot-scope=”props”>
<td >{ props.item.order }</td>
<td class=”text-xs-right”>{ props.item.datetime }</td>
<td >{ props.item.status }</td>
</template>
</v-data-table>

data () {
return {
headers: [
{ … },
{ … },

],
orders: []
}
},

created () {
QueryService.orders().then(response => this.orders = response.data)
}

I know that I can change the state via this.orders now without reloading the whole site, but how can I access the individual rows? They are in the array, so how can I add a new one or change an already existing one if there is 1000 orders? its hard to guess them via an index.

EDIT:

I can’t update the data-table via this.orders = response.data and I don’t know why. The code itself works and I can test via console.log, that this.data is being changed, but the data-table is not being updated!

created () {
setInterval(function() {
QueryService.orders().then(response => this.orders = response.data)
}, 15000)
}

EDIT 2:

I figured out that this.orders which is assigned inside QueryService is not the same orders as the one inside data (), but I still don’t know how to access orders inside data (). I tried this.$data.orders, but it doesn’t work either. Anybody has an idea?

Solution :

The correct way to update an array at an index in a reactive way to is to vm.$set(arr, index, value) See this vue.js doc here.

To find the order, you could search the orders array with Array.findIndex. Really, 1000 items is not that many, especially when they’re loaded into memory already. It’s not optimal, but it should be pretty fast. If you plan to do a lot of searching you might want to maintain an index separately, perhaps in the Vuex store.

// searching for an order by its `order` property.
const targetIndex = this.orders.findIndex(entry => entry.order=orderId)
this.$set(this.orders, targetIndex, modifiedOrder)

EDIT: updated for Vue2 syntax.

Solution 2:

The solution was to use this the right way, because of the scope inside the function. Just define another variable before the function and you can access data() properties.

pollData: function () {

var vm = this;

setInterval(function() {
ContractQueryService.orders().then(response => vm.orders = response.data)
}, 5000)
}

[Vue.js] Vuex state is updated by action but the computed property is not responding

I’m trying to fetch some data from firebase. there is the a store.js, and imported in to the main.js. So the problem is, the data is not correctly printed out when the page is loaded. However, the console.log in mutations shows that the data is fetched correctly as it should. I guess the problem is that, the action is able to fetch the data and update the state, however, the page is rendered before the computed property is changed? Another thing I noticed is, whenever I edit something and save in vscode, the content suddenly shows up, but it goes away if I refresh the page. I think this also means that the data indeed is fetched, but just not showed up. Wondering if anyone can help. Really appreciate it.

// store.js

mport vue.js from ‘Vue’
import Vuex from ‘vuex’
import globalAxios from ‘axios’

Vue.use(Vuex)

export default new Vuex.Store({
state: {
dietRecords: {
breakfest: {},
lunch: {},
dinner: {},
snacks: {}
}
},
mutations: {
setDietRecords (state, data) {
state.dietRecords = data
console.log(state.dietRecords) // this print out correct data
}
},
actions: {
fetchData ({commit, state}) {
globalAxios.get(‘my_data.json’)
.then(res => {
const data = res.data;
const resultArray = {
breakfest: {},
lunch: {},
dinner: {},
snacks: {}
};
for (let key in data) {
resultArray[data[key].meal_type][key] = data[key]
};
commit(‘setDietRecords’, resultArray)
})
}
},
getters: {
dietRecords (state) {
return state.dietRecords
}
}
})

//myapp.vue
import { mapState } from ‘vuex’;
import axios from ‘axios’;
import EditRecord from “./editRecord.vue”

export default {
data: function() {
return {
addRecord: {
breakfest: false,
lunch: false,
dinner: false,
snacks: false
}
}
},
computed: {
diet () {
return this.$store.getters.dietRecords
}
},
methods: {
fetchData() {
this.$store.dispatch(‘fetchDietRecords’)
console.log(this.diet)
}
},
created() {
this.$store.dispatch(‘fetchDietRecords’)
}
}

Solution :

First of all, you’re calling fetchDietRecords action but it’s name is fetchData.
Second of all, the fetchData method is async, meaning that it may take 1 second to make the axios call but the console.log is called immidiately. The solution is to return the promise from the axios call and call then on the returned promise or use async await.

return globalAxios.get(‘my_data.json’) // in the action

First one:

this.$store.dispatch(‘fetchDietRecords’).then(() => {
console.log(this.diet)
})

Second one:

created() {
this.foo()
},
methods: {
async foo() {
await this.$store.dispatch(‘fetchDietRecords’)
console.log(this.diet)
}
}

Hope this helps

[Vue.js] How efficient is `slot-scope` over `v-for`?

How efficient is slot-scope over v-for ?

Isn’t that the both are used for the straight similar purpose?

please correct this if i’m wrong.

Solution :

slot-scopes and slots in general are totally different to v-for.

v-for is used to create a loop bound to a collection.

slot is used to pass DOM elements/data to a component.

slot-scope is used to pass component data to the underlying components - here’s an example:

<json-get url=”/api/v1/users”>
<template slot-scope=”data”>
<ul>
<li v-for=”user in data.results”>{ user.name }</li>
</ul>
</template>
</json-get>

slot-scope=”data” passes info contained within ‘data’ for use of the nested DOM elements.

[Vue.js] Reset current section counter when user manually scrolls up or down

I’m implementing button which will on click vertically scroll down for one team member. So far there is managed that one click scrolls down for one team member, but the code breaks when user manually scrolls back to top.

Here is working JSFiddle

My code

<main class=”team container”>
<div v-for=’(element, index) in members’ :id=”element.specialId” class=”team__member” v-show=”activeIndex === index || widthSmall”>
<div class=”team__member__bio”>
<div class=”team__member__name”>{element.name}</div>
</div>
</div>
<a class=”scroll-more scroll-team” v-show=”widthSmall” @click=”move($event)” style=”cursor: pointer;”>
<span></span>{ $t(‘scroll’) }
</a>
</main>

export default {
name: “Team”,
data() {
return {
members: [
{
name: “Bojan Dovrtel”,
specialId: ‘bojan-div’
},
{
name: “Klemen Razinger”,
specialId: ‘kelemen-div’
},
{
name: “Davor Penik”,
specialId: ‘davor-div’
},
{
name: “Maja Katalini”,
specialId: ‘maja-div’
},
{
name: “Petra Vovk”,
specialId: ‘petra-div’
}
],
secs: document.getElementsByClassName(‘team__member’),
currentSection: 0,
}
},
methods: {
move(e) {
if (this.currentSection < this.secs.length) {
if (this.currentSection === 3) {
this.widthSmall = false;
}
window.scroll({
top: this.secs[++this.currentSection].offsetTop,
left: 0,
behavior: ‘smooth’
});
} else if (this.currentSection > 0) {
window.scroll({
top: this.secs[–this.currentSection].offsetTop,
left: 0,
behavior: ‘smooth’
});

}
}
}
};

How can I detect that users have scrolled up and change the value of current section? If you have any additional informations, please let me know and I will provide. Thank you

Solution :

You could iterate through the elements, finding the closest one whose offsetTop (+ offsetHeight) matches (or be in range of) the current window.scrollY offset as it scrolls, and then decide whether to scroll to the next element or “readjust” the offset:

new Vue({
el: ‘#app’,

data() {
return {
members: [
{
name: “Bojan”,
specialId: ‘bojan-div’
},
{
name: “Klemen”,
specialId: ‘kelemen-div’
},
{
name: “Davor”,
specialId: ‘davor-div’
},
{
name: “Maja”,
specialId: ‘maja-div’
},
{
name: “Petra”,
specialId: ‘petra-div’
}
],
secs: document.getElementsByClassName(‘height’),
currentSection: 0
}
},

mounted() {
this.move();
},

methods: {
move() {
let y = window.scrollY;
let totalSection = this.secs.length;

for (let index = 0; index < totalSection; index++) {
let sec = this.secs[index];

if (sec.offsetTop === y) {
// currentSection matches current window.scrollY, so we want to move to the next section/element
// Math.min() to ensure it won’t go out of range, capping at the length of the total elements.
this.currentSection = Math.min(index + 1, totalSection - 1);

// Or reset the index once it has scrolled all the way down
// this.currentSection = (index + 1) % totalSection;
break;
}
else if (sec.offsetTop >= y && y <= (sec.offsetTop + sec.offsetHeight)) {
// window.scrollY is currently between the matched element’s offsetTop and offsetHeight.
// This is user-initiated scrolling, so let’s just “readjust” the offset rather than scrolling to the next element.
this.currentSection = index;
break;
}
}

window.scroll({
top: this.secs[this.currentSection].offsetTop,
left: 0,
behavior: ‘smooth’
});
}
},
})
.height {
background-color: grey;
height: 300px;
border: solid 2px black;
}

.scroll-team {
position: fixed;
top: calc(100vh - 6rem);
left: 50%;
z-index: 2;
display: inline-block;
-webkit-transform: translate(0, -50%);
transform: translate(0, -50%);
color: #fff;
letter-spacing: 0.1em;
text-decoration: none;
transition: opacity 0.3s;
}

.scroll-team a:hover {
opacity: 0.5;
}

.scroll-more {
padding-top: 60px;
font-size: 1.35rem;
}

.scroll-more span {
position: absolute;
top: 0;
left: 50%;
width: 46px;
height: 46px;
margin-left: -23px;
border: 1px solid #fff;
border-radius: 100%;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.2);
}

.scroll-more span::after {
position: absolute;
top: 50%;
left: 50%;
content: “”;
width: 16px;
height: 16px;
margin: -12px 0 0 -8px;
border-left: 1px solid #fff;
border-bottom: 1px solid #fff;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
box-sizing: border-box;
}

.scroll-more span::before {
position: absolute;
top: 0;
left: 0;
z-index: -1;
content: “”;
width: 44px;
height: 44px;
box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.1);
border-radius: 100%;
opacity: 0;
-webkit-animation: sdb03 3s infinite;
animation: sdb03 3s infinite;
box-sizing: border-box;
}
<script src=”https://unpkg.com/vue"></script>

<div id=”app”>
<div class=”height” v-for=”(element, index) in members” :key=”index”>
{ element.name }
</div>
<a class=”scroll-more scroll-team” @click=”move” style=”cursor: pointer;”>
<span></span>
</a>
</div>

Solution 2:

To detect that a user has scrolled, you can listen for the scroll event on the container that is being scrolled. In this case, that would be the root element, so you can use window to add the event listener.

One way to do achieve that would be to add and remove the scroll listener in the created and destroyed lifecycle hooks, as mentioned in this answer.

Note that the scroll event will also be fired when you trigger a scroll with window.scroll({…}), not just user scrolling. So, you’ll need to take care of that.

I’d recommend adding some kind of throttle to the scroll event listener and then responding to all scroll events, post throttle, by changing the currentSection value.

For example, the scroll event handler can be:

…,
onScroll(e) {
if(this.throttle) {
clearTimeout(this.throttle);
}

this.throttle = setTimeout(() => (this.currentSection = this.findCurrentSection(e)), 300);
},

Where throttle is just a data member used to hold the timeout value. The logic to find the value of currentSection will only be triggered 300ms after the last scroll event. You can also use requestAnimationFrame to do this, as mentioned here.

findCurrentSection is just a basic method that iterates over the secs array to find, well, the current section based on the current scroll value.

…,
findCurrentSection(e) {
const curTop = document.documentElement.scrollTop;
for(let i=0, len=this.secs.length; i < len; ++i) {
const secTop = this.secs[i].offsetTop;
if(curTop === secTop) {
return i;
} else if(curTop < secTop) {
return Math.max(i-1, 0);
}
}
},

Note that since in this particular case the scrolling container is the root element, I’m using document.documentElement.scrollTop, but based on the context, you can get the required value from the corresponding ScrollEvent (e in this case).

Here’s a working fiddle based on the question. Also note that there is modified the move function according to the changes introduced.

[Vue.js] Vue.js component for picking hours

I’m creating an application where users can order Services on specific hours. Once a Service is picked for, say 2:00pm, Feb21, no other user can order a Service for this hour (but can for 1pm and 3pm).

I’ve googled for “vue.js date picker”, “vue.js hour table”, here’s a very long list of Solutions: https://github.com/vuejs/awesome-vue/blob/master/README.md but all of them are to select dates, and there’s no way to indicate that a specific hour is unavailable. Is there’s any such component?

I imagine it as a table, where columns are days, and rows are continuous hours makred either available or unavailable

Solution :

I think you can use https://www.npmjs.com/package/vue-bootstrap-datetimepicker or http://eonasdan.github.io/bootstrap-datetimepicker/ directly without vue.

Solution 2:

ElementUI, a vue.js component library, has this timepicker component.

I think the selectableRange may allow you to exclude hours from the timepickers dinamically, by passing custom available ranges. How to implement this depends a lot on the own code, though.