So, there are nth number of string value. One by one I need to display those string value on single snackbar after an interval. For example - "This is snackbar one" should get displayed for 1 min after that again "This is snackbar two" should get displayed.
Currently, I am getting all text in snackbar.Refer below image -
HTML template -
<template>
<div>
<v-app light>
<v-snackbar
v-model="snackbar"
:multi-line="mode === 'multi-line'"
:timeout="timeout"
:top="y === 'top'"
:color="'success'"
:messages.sync="messages"
>
<div>{{ text }}</div>
<v-btn #click="snackbar = false"> X </v-btn>
</v-snackbar>
</v-app>
</div>
</template>
<script>
export default {
data () {
return {
snackbar: true,
y: "top",
x: "right",
mode: "",
timeout: 6000,
text: [
"This is Snackbar ONE",
"This is Snackbar TWO",
"This is Snackbar THREE",
"This is Snackbar FOUR",
"This is Snackbar FIVE",
"This is Snackbar SIX",
"This is Snackbar SEVEN",
],
indexText: 0,
messages: [],
};
},
async created() {
showMessage() {
console.log('this.text : ', this.text)
if (this.indexText >= this.text.length) this.indexText = 0;
this.messages.push(this.text[this.indexText++]);
console.log('this.messages : ', this.messages)
},
},
};
</script>
Also adding SS for console.log -
You have an issue in your code, the created hook is asynchronous, so you cannot call the showMessage function inside the created hook. Instead, you should call the showMessage function inside the mounted hook.
Also, you need to set an interval to call the showMessage function after certain interval.
Here's the updated code, hope it helps:
<template>
<div>
<v-app light>
<v-snackbar
v-model="snackbar"
:multi-line="mode === 'multi-line'"
:timeout="timeout"
:top="y === 'top'"
:color="'success'"
:messages.sync="messages"
>
<div>{{ text }}</div>
<v-btn #click="snackbar = false"> X </v-btn>
</v-snackbar>
</v-app>
</div>
</template>
<script>
export default {
data() {
return {
snackbar: true,
y: "top",
x: "right",
mode: "",
timeout: 6000,
text: [
"This is Snackbar ONE",
"This is Snackbar TWO",
"This is Snackbar THREE",
"This is Snackbar FOUR",
"This is Snackbar FIVE",
"This is Snackbar SIX",
"This is Snackbar SEVEN",
],
indexText: 0,
messages: [],
};
},
methods: {
showMessage() {
if (this.indexText >= this.text.length) this.indexText = 0;
this.messages.push(this.text[this.indexText++]);
},
},
mounted() {
setInterval(() => {
this.showMessage();
}, 1000);
},
};
</script>
In the above code, I have added a mounted hook and inside that, I have set an interval of 1 sec (1000 ms) which will call the showMessage function after every 1 sec.
Related
I'm currently struggling with returning the id of a specific field from each row. I need this id to use it as a parameter for a function that will be used in an action button to delete the row.
This is how my table template is looking like:
<template v-slot:top>
<v-toolbar flat>
<v-toolbar-title>Publicații</v-toolbar-title>
<v-divider class="mx-4" inset vertical> </v-divider>
<v-text-field
v-model="search"
append-icon="mdi-magnify"
label="Caută"
single-line
clearable
class="shrink"
hide-details=""
></v-text-field>
<v-divider class="mx-4" inset vertical> </v-divider>
<v-btn
color="orange"
v-on:click="
changeRoute();
arataDialogEditare = true;
"
v-show="arataBtnAdaugare"
>{{ txtBtnAdaugaNou }}
</v-btn>
</v-toolbar>
</template>
<template v-slot:[`item.actiuni`]>
<v-btn color="primary" fab x-small elevation="2">
<v-icon>edit</v-icon>
</v-btn>
<v-btn
v-on:click="deletePublication()"
color="primary"
fab
x-small
elevation="2"
>
<v-icon>delete_forever</v-icon>
</v-btn>
</template>
</v-data-table>
</template>
This is how my headers are looking like (my headers is dynamically loaded, that's why I have more than one) :
headers: [],
headersInitial: [
{
text: "Id publicatie",
value: "ID",
},
{
text: "Tip publicație",
value: "tipPublicatie",
},
{
text: "Nume publicație",
value: "titluPublicatie",
},
{
text: "An publicație",
value: "an",
},
{
text: "Actions",
value: "actions",
sortable: false,
},
],
headersFaraTipPublicatii: [
{
text: "Id publicatie",
value: "ID",
},
{
text: "Nume publicație",
value: "titluPublicatie",
},
{
text: "An publicație",
value: "an",
},
{
text: "Actions",
value: "actions",
sortable: false,
},
],
publicatii: [],
publicatiiCuFiltru: [],
This is how I get my data into the table:
initialize() {
this.headers = this.headersInitial;
axios.get("https://localhost:44349/api/items/ReturnarePublicatii").then((returnPub) => {
this.publicatii = returnPub.data;
this.publicatiiCuFiltru = returnPub.data
});
},
Here is my delete function:
deletePublication() {
let ID = this.headersInitial.ID
if (confirm('Are you sure you want to delete the record?')) {
axios.get("https://localhost:44349/api/items/StergereItem/" + ID).then((returnPub) => {
this.publicatii = returnPub.data;
this.publicatiiCuFiltru = returnPub.data
});
}
},
Whenever I try to delete a record, this error occurs: "Uncaught (in promise) Error: Request failed with status code 400". How can I make it work?
let ID = this.headersInitial.ID
this.headersInitial is an array - it has no property ID
Your deletePublication() method needs to receive the id of the row as a parameter (because it can be called for different rows always with different id)
That's why Vuetify passes the actual row into a item slot as a prop. Replace v-slot:item.actiuni with v-slot:item.actiuni="{ item }" as shown in the example. The item is the object (current row) and you can use it in your handler as v-on:click="deletePublication(item.ID)
I have an array of elements, I need to render those elements in to a div and attach different on-click functions to each.
<template>
<div class="container">
<div v-for="option in options" :key="option.id" #click="option.clickFunction">.
{{option}}
</div>
</div>
</template>
<script>
export default{
data(){
return{
options: [
{
id: 1,
text: "option 1",
clickFunction: "function1",
},
{
id: 2,
text: "option 2",
clickFunction: "function2",
},
{
id: 3,
text: "option 3",
clickFunction: "function3",
},
{
id: 4,
text: "option 4",
clickFunction: "function4",
},
{
id: 5,
text: "option 5",
clickFunction: "function5",
},
],
}
}
methods:{
//defining all click functions
}
}
</script>
I have tried the above approach but its not working, is there any way of doing this?
This isn't working for you because each clickFunction property in each object is a string. What is the #click attribute supposed to do with a regular old string? Try
<template>
<div class="container">
<div v-for="option in options" :key="option.id" #click="option.clickFunction">
<!-- I'm guessing you meant option.text here -->
{{option.text}}
</div>
</div>
</template>
<script>
export default{
data(){
return{
// pass functions around instead of strings!
options: [
{
id: 1,
text: "option 1",
clickFunction: this.myUniqueClickHandler,
},
{
id: 2,
text: "option 2",
clickFunction: this.myOtherUniqueClickHandler,
},
// etc.
],
}
}
methods:{
myUniqueClickHandler() {
// ...
},
myOtherUniqueClickHandler() {
// ...
}
}
}
</script>
I think you want to listen for each item's onclick. So, you need to declare only one method or function for all, and pass the key value of each item as a parameter. Then, use a switch statement or if statement to detect which option is clicked.
I have changed your code as bellow:
<template>
<div class="container">
<div v-for="option in options" :key="option.id" #click="myFunction(option.id)">.
{{option}}
</div>
</div>
</template>
<script>
export default{
data(){
return{
}
}
methods:{
myFunction(id) {
switch (id) {
case 1:
// option 1 is clicked
break;
case 2:
// option 2 is clicked
break;
case 3:
// option 3 is clicked
break;
case 4:
// option 4 is clicked
break;
default:
break;
}
}
}
}
</script>
A small app where user needs to select either Yes or No for each task. The user should NOT be allowed to leave the page unless they have answered all questions. I have added a button at the bottom of the form which simulates beforeRouterLeave behaviour.
My question is about the simulateBeforeRouteLeave() function. How can do I check if all questions have been answered to allow user to leave?
Ps. This is a snipped from a much larger project. The original data comes from a API and its NOT hard coded like in this example.
CodeSandbox
App.vue
<template>
<parent-component
v-for="task in tasks.data"
:key="task.id"
:taskData="task"
#update-form-data="handleChange"
>
</parent-component>
<button
class="my-2 border-2 border-red-500"
#click="simulateBeforeRouteLeave"
>
simulateBeforeRouteLeave
</button>
</template>
<script>
import parentComponent from "./components/parentComponent.vue";
export default {
components: {
parentComponent,
},
methods: {
simulateBeforeRouteLeave() {
//Need HELP Here! How do I write this IF statement?
if ("Options_NOT_Selected") {
alert("Please select all options");
} else {
console.log("Allow user to leave 'next()'");
}
},
handleChange(e) {
const objIndex = this.tasks.data.findIndex((obj) => obj.id === e.id);
this.tasks.data[objIndex].status = e.status;
},
},
data() {
return {
markAll: false,
tasks: {
data: [
{
id: 1,
name: "Task 1",
status: null,
},
{
id: 2,
name: "Task 2",
status: null,
},
{
id: 3,
name: "Task 3",
status: null,
},
],
},
};
},
};
</script>
parentComponent.vue
<template>
<div class="py-2">
<div>
<input
type="radio"
:id="taskData.id + 'Yes'"
:name="taskData.name"
:value="taskData.value"
#change="updateData"
/>
<label :for="taskData.id">{{ taskData.name }} Yes</label>
</div>
<div>
<input
type="radio"
:id="taskData.id + 'No'"
:name="taskData.name"
:value="taskData.value"
/>
<label :for="taskData.id">{{ taskData.name }} No</label>
</div>
</div>
</template>
<script>
export default {
props: ["taskData"],
methods: {
updateData(e) {
this.$emit("update-form-data", {
id: this.taskData.id,
status: 1,
});
},
},
data() {
return {};
},
};
</script>
I am trying to create a form similar to google forms. Whenever a user inserts image I want to preview the image. Now, I have created a function updateImageLink to update the state once user inserts image. The function is below:
updateImageLink = (link, position) => {
let questions = [...this.state.questions];
let i = position.question;
if (position.option == null) {
questions[i].questionImage = link;
} else {
var j = position.option
questions[i].options[j].optionImage = link;
}
this.setState({ questions });
}
Suppose the user wants to delete the image so for that I have created a delete button and passed the function through onClick prop as follows:
<IconButton
style={{
marginLeft: "3px",
marginTop: "-15px",
zIndex: 999,
backgroundColor: "lightgrey",
color: "grey",
}}
size="small"
onClick={() => {
this.updateImageLink("", { question: i, option: null });
}}
>
<CloseIcon />
</IconButton>
Now, this code renders the CloseIcon even when there's no image. The problem is with binding the function. If I write:
onClick={this.updateImageLink("", { question: i, option: null })}
Then CloseIcon does not render and the state does not get updated as well.
The state of class is as follows:
this.state = {
questions: [
{
questionText: "Question 1",
questionImage:null,
options: [
{ optionText: "Option 1",
optionImage: null },
{ optionText: "Option 2",
optionImage: null },
{ optionText: "Option 3",
optionImage: null },
{ optionText: "Option 4",
optionImage: null }
],
correctAnswer: ""
}
],
openUploadImagePop: false,
imagePositionData: {
question: null,
option: null
}
}
So, how to render the CloseIcon only when the image is inserted?
I solved this question by updating the state as follows:
this.state = {
questions: [
{
questionText: "Question 1",
options: [
{ optionText: "Option 1" },
{ optionText: "Option 2" },
{ optionText: "Option 3" },
{ optionText: "Option 4" }
],
correctAnswer: ""
}
],
openUploadImagePop: false,
imagePositionData: {
question: null,
option: null
}
};
}
Here as there's no questionImage or optionImage field the unnecessary CloseIcon rendering problem is solved. Whenever, image is uploaded questionImage or optionImage gets added in the state through updateImageLink function.
I'm trying to save the value of a radio button dynamically loaded into an array of object. Thoose radios are options for a series of questions of a form, and i would like to get something like:
[{"question1":{
"selected": <id>,
...
},...]
But i don't know how should I define the data or how to reference it wiht the v-model attribute of the radio group.
This is my best try:
<v-radio-group v-model="answers[question.question_id]">
<v-row justify="center">
<v-col v-for="option in question.options" :key="option.option_id">
<v-radio
:label="option.option_text"
:name="question.question_id"
:value="option.option_id"
></v-radio>
</v-col>
</v-row>
</v-radio-group>
And data:
data: () => ({
...
answers: [],
...
}),
What I get rom this is somehting like: [anwswer_id1, anwswer_id1...], witch is close, but not exactly what I need
a simple way could be like this:
<template>
<v-layout column>
<v-radio-group v-model="questions[questionIndex][currentQuestionId].selected">
<v-row justify="center">
<v-col v-for="(option,i) in questions[questionIndex][currentQuestionId].options" :key="i">
<v-radio :label="option.text" :name="currentQuestionId" :value="option._id"></v-radio>
</v-col>
</v-row>
</v-radio-group>
<v-btn #click="handleClickButtonNext">next question</v-btn>
<v-btn #click="handleClickButtonPrev">previous question</v-btn>
</v-layout>
</template>
<script>
export default {
data() {
return {
questions: [
{
question0: {
selected: null,
options: [
{
text: "text 1",
_id: 1
},
{
text: "text 2",
_id: 2
},
{
text: "text 3",
_id: 3
}
]
}
},
{
question1: {
selected: null,
options: [
{
text: "text 2",
_id: 2
},
{
text: "text 3",
_id: 3
},
{
text: "text 4",
_id: 4
}
]
}
},
],
questionIndex: 0
};
},
computed: {
currentQuestionId() {
return "question" + this.questionIndex;
}
},
methods: {
handleClickButtonNext() {
if (this.questionIndex < this.questions.length-1) this.questionIndex++;
},
handleClickButtonPrev() {
if (this.questionIndex > 0) this.questionIndex--;
},
}
};
</script>
where:
questionIndex - keeps track of the current question index
currentQuestionId - gives you the current question id
handleClickButtonNext / handleClickButtonPrev - lets you jump between the questions
This is a way if you just want to show 1 question at a time.
Otherwise, you could also get rid of keeping track of the index, and loop the questions array:
<template>
<v-layout column>
<v-radio-group
v-for="(question, j) in questions"
:key="j"
v-model="question[`question${j}`].selected"
>
<v-row justify="center">
<v-col v-for="(option,i) in question[`question${j}`].options" :key="i">
<v-radio :label="option.text" :name="`question${j}`" :value="option._id"></v-radio>
</v-col>
</v-row>
</v-radio-group>
</v-layout>
</template>
<script>
export default {
data() {
return {
questions: [
{
question0: {
selected: null,
options: [
{
text: "text 1",
_id: 1
},
{
text: "text 2",
_id: 2
},
{
text: "text 3",
_id: 3
}
]
}
},
{
question1: {
selected: null,
options: [
{
text: "text 2",
_id: 2
},
{
text: "text 3",
_id: 3
},
{
text: "text 4",
_id: 4
}
]
}
}
]
};
}
};
</script>