How to run 2 functions simultaneously in vuejs - vue.js

I wanted to run 2 functions simultaneously in VUE. One function will be called when component is mounted and it will be running every 10 seconds. The other function will start executing when we click on the button.
Now my problem is when I click the button the function start executing and the first function will not be called till this function completed its execution.
<template>
<div>
<select v-model="file_id" class="form-control" id="">
<option v-for="(file, index) in files" :value="file.value" :key="index">
{{ file.label }}
</option>
</select>
<button class="btn btn-success" #click="handleFileUpload">Import</button>
</div>
</template>
<script>
export default {
data() {
return {
files: [],
};
},
mounted() {
this.upload_status = setInterval(() => {
this.getUploadedStatus();
}, 5000);
},
methods: {
handleFileUpload() {
//it will start executing when we click the button (need to call API)
axios.post();
},
getUploadedStatus() {
//it has to run every 10 seconds (Need to call API)
axios.get();
},
beforeDestroy() {
clearInterval(this.upload_status);
},
},
};
</script>

Related

Remove dynamically-added Vue component

I'm updating a form built with Vue that lets you dynamically add and remove blocks of fields. Currently, it's set up so that the add and remove buttons are at the bottom of the interface and the remove button removes blocks in the reverse order of how they're added.
Now I need to update it so that each block or row has its own remove button so that you can remove any block. Because at the moment, if you add 10 blocks, and then decide you want to remove the first one, you have to remove all others first.
I've created a Vue Sandbox to illustrate. At the moment, even though I've got remove buttons per row, they're still only removing the rows in reverse order as before. That's because the remove function is just reducing the index by 1 each time.
But I'm not sure what I need to update though so that it removes the component matching the id of the button you click on.
Parent component
<template>
<div>
<component
:is="fieldType"
v-for="i in index"
:key="i"
:index="i"
#add="add"
#remove="remove"
/>
<div>
<button type="button" #click="add">Add {{ label }}</button>
</div>
</div>
</template>
<script>
import textField from "./textField";
export default {
components: {
textField,
},
props: {
fieldType: {
type: String,
required: true,
},
label: {
type: String,
default: "",
}
},
data: () => ({
index: 0,
}),
methods: {
add() {
this.index += 1;
},
remove() {
this.index -= 1;
},
},
};
</script>
Child component
<template>
<div>
<label :for="'text-' + index" v-text="'Text' + index"></label>
<input :id="'text-' + index" type="text" name="" />
<button v-if="index" type="button" #click="$emit('remove', index)">
Remove
</button>
</div>
</template>
<script>
export default {
props: {
index: {
type: Number,
required: true,
},
},
};
</script>

How to use parameters in Axios (vuejs)?

Good morning Folks,
I got an API from where I am getting the data from.
I am trying to filter that with Axios but I don`t get the result that I am expecting.
I created a search box. I created a computed filter and that I applied on the Axios.
I would like to see only the searched results in my flexboxes (apart from the last three articles as a start)
<template>
<div id="app">
<div class="search-wrapper">
<input
type="text"
class="search-bar"
v-model="search"
placeholder="Search in the titles"
/>
</div>
<paginate
ref="paginator"
class="flex-container"
name="items"
:list="filteredArticles"
>
<li
v-for="(item, index) in paginated('items')"
:key="index"
class="flex-item"
>
<div id="image"><img :src="item.image && item.image.file" /></div>
<div id="date">{{ formatDate(item.pub_date) }}</div>
<div id="title">{{ item.title }}</div>
<div id="article" v-html="item.details_en" target="blank">
Explore More
</div>
</li>
</paginate>
<paginate-links
for="items"
:limit="2"
:show-step-links="true"
></paginate-links>
</div>
</template>
<script>
import axios from "axios";
import moment from "moment";
export default {
data() {
return {
items: [],
paginate: ["items"],
search: "",
};
},
created() {
this.loadPressRelease();
},
methods: {
loadPressRelease() {
axios
.get(
`https://zbeta2.mykuwaitnet.net/backend/en/api/v2/media-center/press-release/?page_size=61&type=5`,
{ params }
)
.then((response) => {
this.items = response.data.results;
});
},
formatDate(date) {
return moment(date).format("ll");
},
openArticle() {
window.open(this.items.details_en, "blank");
},
},
computed: {
axiosParameters() {
const params = new SearchParams();
if (!this.search) {
return this.items;
}
return this.items.filter((item) => {
return item.title.includes(this.search);
});
},
},
};
</script>
Here is the basic code for implementing vue watcher along with the debounce for search functionality.
import _ from "lodash" // need to install lodash library
data() {
return {
search: "",
};
},
watch:{
search: _.debounce(function (newVal) {
if (newVal) {
// place your search logic here
} else{
// show the data you want to show when the search input is blank
}
}, 1000),
}
Explanation:
We have placed a watcher on search variable. Whenever it detects any change in search variable, it will execute the if block of code if it's value is not empty. If the value of search variable goes empty, it will execute else block.
The role of adding debounce here is, it will put a delay of 1 sec in executing the block of code, as we don't want to execute the same code on every single character input in the search box. Make sure you install and import lodash library. For more info on Lodash - Debounce, please refer here.
Note: This is not the exact answer for this question, but as it is asked by the question owner in the comment section, here is the basic example with code.

How to prevent a submit button on a form to be clicked multiple times in VUEJS

I want to prevent users from clicking on the submit button multiple times. How would I accomplish that in the following template and script?
Excerpt of template:
<form #submit.prevent="onSubmit">
<b-button
v-on:click="disable"
variant="danger"
type="submit"
>
Compléter
</b-button>
</form>
..and script:
onSubmit() {
this.$v.status.$touch();
if (!this.$v.$invalid) {
/////
}
},
You could set a Boolean flag (e.g., named submitting) that disables the button during the form submission process. The <b-button> supports a disabled state with the disabled attribute, which could be bound to submitting:
<b-button :disabled="submitting">Compléter</b-button>
Example:
<template>
<form #submit.prevent="onSubmit">
<b-button :disabled="submitting">Compléter</b-button>
</form>
</template>
<script>
export default {
data() {
return {
submitting: false,
}
},
methods: {
async onSubmit() {
if (!this.submitting) {
this.submitting = true
try {
await this.longSubmit()
} finally {
this.submitting = false
}
}
}
//...
}
}
</script>
demo

Retrieve data attribute value of clicked element with v-for

I've made a datalist which is filled dynamically and it works correctly.
Now, I need listen the click event on the options to retrieve the data-id value and put it as value in the input hidden.
I already tried with v-on:click.native and #click but there is no response in the console.
Any idea? I'm just starting at Vue, hope you can help me.
Edit:
Looks like it doesn't even fire the function. I've tried v-on:click="console.log('Clicked')" but nothing happens.
<input type="hidden" name="id_discipline" id="id_discipline">
<input list="disciplines" id="disciplines-list">
<datalist id="disciplines">
<option
v-for="discipline in disciplines"
:key="discipline.id_discipline"
:data-id="discipline.id_discipline"
v-on:click="updateDisciplineId($event)"
>{{discipline.name}}</option>
</datalist>
methods: {
updateDisciplineId(event) {
console.log('clicked!);
}
},
Using datalist is not suited for what you want to acheive, however there's a workaround with a limitation.
Template:
<template>
<div>
<input
type="text"
name="id_discipline"
v-model="selectedID"
placeholder="Data id value of clicked"
/>
<input
#input="onChange"
list="disciplines"
id="disciplines-list"
class="form-control"
placeholder="Seleccionar disciplina"
/>
<datalist id="disciplines">
<option
v-for="discipline in disciplines"
:key="discipline.id_discipline"
:data-value="discipline.id_discipline"
>{{ discipline.name }}</option
>
</datalist>
</div>
</template>
Script Part:
<script>
export default {
data() {
return {
selectedID: "",
id_discipline: "",
disciplines: [
{
id_discipline: 1,
name: "Yoga"
},
{
id_discipline: 2,
name: "Functional"
}
]
};
},
methods: {
onChange(e) {
this.getID(e.target.value).then(
resposnse => (this.selectedID = resposnse)
);
},
async getID(value) {
let promise = new Promise((resolve, reject) => {
this.disciplines.forEach(item => {
if (item.name === value) resolve(item.id_discipline);
});
});
return await promise;
}
}
};
</script>
Here's a working Sandbox demo.
**Limitation: Discipline name (Yoga, functional) should be unique.

How can I update value in input type text on vue.js 2?

My view blade laravel like this :
<form slot="search" class="navbar-search" action="{{url('search')}}">
<search-header-view></search-header-view>
</form>
The view blade laravel call vue component (search-header-view component)
My vue component(search-header-view component) like this :
<template>
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search" name="q" autofocus v-model="keyword" :value="keyword">
<span class="input-group-btn">
<button class="btn btn-default" type="submit" ref="submitButton"><span class="fa fa-search"></span></button>
</span>
<ul v-if="!selected && keyword">
<li v-for="state in filteredStates" #click="select(state.name)">{{ state.name }}</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: 'SearchHeaderView',
components: { DropdownCategory },
data() {
return {
baseUrl: window.Laravel.baseUrl,
keyword: null,
selected: null,
filteredStates: []
}
},
watch: {
keyword(value) {
this.$store.dispatch('getProducts', { q: value })
.then(res => {
this.filteredStates = res.data;
})
}
},
methods: {
select: function(state) {
this.keyword = state
this.selected = state
this.$refs.submitButton.click();
},
input: function() {
this.selected = null
}
}
}
</script>
If I input keyword "product" in input text, it will show autocomplete : "product chelsea", "product liverpool", "product arsenal"
If I click "product chelsea", the url like this : http://myshop.dev/search?q=product
Should the url like this : http://myshop.dev/search?q=product+chelsea
I had add :value="keyword" in input type text to udpate value of input type text, but it does not work
How can I solve this problem?
Update
I had find the solution like this :
methods: {
select: function(state) {
this.keyword = state
this.selected = state
const self = this
setTimeout(function () {
self.$refs.submitButton.click()
}, 1500)
},
...
}
It works. But is this solution the best solution? or there is another better solution?
Instead of timeout you can use vue's nextTick function.
I didn't checked your code by executing but seems its problem regarding timings as when submit is pressed your value isn't updated.
so setTimeout is helping js to buy some time to update value, but its 1500 so its 1.5 second and its little longer and yes we can not identify how much time it will take each time so we tempted to put max possible time, still its not perfect solution
you can do something like this. replace your setTimeout with this one
const self = this
Vue.nextTick(function () {
// DOM updated
self.$refs.submitButton.click()
})
nextTick will let DOM updated and set values then it will execute your code.
It should work, let me know if it works or not.