I need to pass a VueJS variable to a VueJs function without the page submitting. For some reason the form is still submitting after passing the variable through to the function.
HTML
<div class="list-group-item" v-for="event in events">
<form method="POST" v-on:submit.prevent="deleteEvent('#{{ event.id }}')")>
<b><h1>#{{ event.name }}</h1></b>
<hr>
<small>#{{ event.description }}</small>
<hr>
<b>#{{ event.date }}</b>
<hr>
<button class="btn btn-danger form-control">Delete</button>
</form>
</div>
JavaScript
new Vue({
el: '#app',
data: {
newEvent: {
name: '',
description: '',
date: ''
}
},
ready: function(){
this.retrieveEvents();
},
methods: {
retrieveEvents: function(){
this.$http.get('/retrieveEvents', function(response){
this.$set('events', response);
});
},
addEvent: function(e){
e.preventDefault();
var event = this.newEvent;
this.$http.post('/addEvent', event, function(){
this.newEvent = {name: '', description: '', date: ''};
});
this.retrieveEvents();
},
deleteEvent: function(id){
e.preventDefault();
console.log(id);
}
}
});
I don't see why it keeps submitting the form and not passing the variable into VuejJS, everything else works perfectly.
You don't need to interpolate in the binding syntax, you can access the properties directly:
<form method="POST" v-on:submit.prevent="deleteEvent(event.id)">
Related
I'm new in vue, and I am trying to make a get request from a field that has a v-model="embed.url" after pasting the link. Event after paste works well but, I don't know how to reference to input with v-model="embed.url" and get the data.
When I try code below error appear:
[Vue warn]: Error in v-on handler: "ReferenceError: embed is not defined"
and
ReferenceError: "embed is not defined"
My vue code:
<script type="text/javascript">
axios.defaults.xsrfHeaderName = "X-CSRFToken";
new Vue({
el: '#app',
delimiters: ['!!', '!!'],
data () {
return {
embed: {
url: '',
title: '',
description: '',
type: '',
thumbnail_url: '',
html: '',
},
isPaste: false,
embedsinfo: [],
}
},
methods: {
formSubmit(e) {
e.preventDefault();
let currentObj = this;
axios.post('http://wegemoc.local:8000/recipes/recipe/embed/add/', {
url: this.url,
})
.then(function (response) {
currentObj.output = response.data;
})
.catch(function (error) {
currentObj.output = error;
});
},
paste() {
this.isPaste = true;
},
input() {
if (this.isPaste) {
axios.get('http://iframe.ly/api/oembed?url=' + embed.url + '&api_key=493c9ebbdfcbdac2a10d6b')
.then(response => (this.embedsinfo = response))
isPaste = false;
}
}
},
});
My form:
<div id="app">
!! embedsinfo.title !!
<form method="post" class="margin-bottom-25" #submit="formSubmit">
{% csrf_token %}
<div class="form-group">
<label for="formGroupExampleInput">Adres przepisu*</label>
<input type="url" class="form-control" placeholder="Url" #paste="paste" #input="input" v-model="embed.url">
</div>
<div class="form-group">
<label for="formGroupExampleInput2">Tytuł</label>
<input class="form-control" placeholder="Title" v-model="embed.title">
</div>
<div class="form-group">
<label for="formGroupExampleInput2">Description</label>
<input type="textarea" class="form-control" id="formGroupExampleInput2" placeholder="Description" v-model="embed.description">
</div>
<div class="form-group">
<label for="formGroupExampleInput2">Thumbnail_url</label>
<input type="text" class="form-control" id="formGroupExampleInput2" placeholder="Tthumbnail_url" v-model="embed.thumbnail_url">
</div>
<button type="submit" class="btn btn-success-gradiant">Dodaj link</button>
</form>
</div>
When you are not using Vue as Single Component files, your data property must be an object and not a function. Change your data property to an object and then give it a try.
new Vue({
el: '#app',
delimiters: ['!!', '!!'],
data: {
return {
embed: {
url: '',
...
};
},
...
Also you must access your data embed.url property using "this" like how you have referenced other properties in your code.
if (this.isPaste) {
axios.get('http://iframe.ly/api/oembed?url=' + this.embed.url + '&api_key=493c9ebbdfcbdac2a10d6b')
.then(response => (this.embedsinfo = response))
isPaste = false;
}
I build following component:
var Modal = Vue.component('modal', {
template: `
<div id="modal" class="modal">
<div class="modal-content">
<p>{{ link }}</p>
</div>
</div>
`,
props: [
'link'
],
});
And I would like to change the link data dynamically after I sent successfully an axios post.
My vue instance
new Vue({
el: '#form',
components: {
'modal': Modal
},
data: {
userId: '',
title: '',
body: '',
snippetLink: '',
},
methods: {
publish (e) {
var self = this;
axios.post('/snippets', {
title: this.title,
body: this.content,
})
.then(function (response) {
console.log("success");
self.link = response.data.hash; // Here I tried to add the reponse content to the vue component's p
})
.catch(function (error) {
console.log(error);
})
},
My Html Markup:
<modal link=""></modal>
...
<button type="button"
v-bind:class="{ 'modal-trigger': !isActiveModal }"
#click="publish">Publish
<i class="material-icons right">send</i>
</button>
So I am sending an axios post to my server successfully and get the data, I would like to open a modal window and put the data in a p tag, so far the modal pops up after my post but I am not sure my it does not change the content of the p tag.
As per my understanding , Snippetlink property can be used to hold data from server.
self.Snippetlink = response.data.hash;
and Pass Snippetlink to link attribute of the snippet-model
<snippet-modal :link="Snippetlink"></snippet-modal>
rupesh_padhye's answer is correct. This is just a further explanation.
First of all, to store the response data to a Vue component, you need to define a key in data for that purpose first. So to make this line work: self.link = response.data.hash;, you need to add link as a key for the Vue component's data:
data: {
userId: '',
title: '',
body: '',
snippetLink: '',
link: ''
},
If you mean snippetLink, change the line to self.snippetLink = response.data.hash;
Secondly, to pass the data as a prop to a child component, you have to specify the prop name, as well as the data key being passed. For instance, to pass your component's link as a prop with the same name to the snippet-modal component, you need: <snippet-modal :link="link"></snippet-modal>
I have the code below, the 'tarefas' variable is not appear in my v-for, and I verify the response from the server and its ok, the data are coming. When I add new data in the input field, it works correctly
JS:
var app = new Vue({
el: '#app',
data: {
titulo: 'Lista de Tarefas',
tarefas: [],
tarefa: ''
},
methods: {
addTarefa: function () {
console.log(this.tarefa);
if (this.tarefa !== '') {
this.tarefas.push({identificador: 0, descricao: this.tarefa, feito: 0});
this.postTasks();
//this.tarefa = '';
}
},
removerTarefa: function (tarefa) {
this.tarefas.splice(this.tarefas.indexOf(tarefa), 1)
},
syncTasks: function () {
jQuery.get('http://localhost:51622/api/tarefa', function (data, status) {
this.tarefas = data;
console.log(data);
console.log(this.tarefas);
});
},
postTasks: function () {
jQuery.post('http://localhost:51622/api/tarefa', {identificador: 0, descricao: this.tarefa, feito: 0});
},
},
created: function () {
console.log("passei no mounted");
this.syncTasks();
},});
HTML:
<p class="text-primary center">{{ titulo }}</p>
<div class="col-xs-3">
<input type="text" placeholder="digite a tarefa" v-model="tarefa" class="form-control" />
</div>
<button v-on:click="addTarefa" class="btn btn-default">add tarefa</button>
<br />
<br />
<div class="col-xs-3">
<ul class="list-group">
<li v-for="tarefa in tarefas" class="list-group-item">{{ tarefa }} <button class="btn" v-on:click="removerTarefa(tarefa)">X</button></li>
</ul>
</div>
</div>
</div>
<script src="app.js"></script>
Since your callback is a regular function, your this is not pointing to the Vue. Try an arrow function.
jQuery.get('http://localhost:51622/api/tarefa', (data, status) => {
this.tarefas = data;
console.log(data);
console.log(this.tarefas)
});
See How to access the correct this inside a callback?
I am trying to bind an attribute to and id I have on a button to change its styling, basically I have a courses database table(using Laravel as backend) where each course has a Boolean named completed, All I want to do is if the course is completed(true) to render a specific id, and if it is not(false) to render another one, that's it, here's my code,
This is the blade template, this is inside a table:
<td>
<form method="POST" action="{{ route('course.completed', $course->name) }}" id="form-submit">
{{ csrf_field() }}
#if ($course->completed)
<button #click.prevent="onSubmit({{ $course }})" type="button" class="btn btn-sm" :id="cssClass">#{{ text }}</button>
#endif
</form>
And here is the vue instance, All i want to do here is to add an if condition that will set the cssClass properly to the name of the id that I want:
<script>
new Vue({
el: '#app',
data: {
cssClass: '',
text: ''
},
methods: {
onSubmit: function(course) {
axios.post('/MyCourses/' + course.name)
// .then(function (response){
// });
}
},
//Basically here's what I would like to be able to do
if (course.completed == true) {
this.cssClass = 'coursetogglingtrue',
this.text = 'Done!'
} else {
this.cssClass = 'coursetogglingfalse',
this.text = 'Not Yet!'
}
});
</script>
Right now the above code in the view instance errors out with "Uncaught SyntaxError: Unexpected token ." directed at the if statement course.completed, and it doesn't go away unless I delete the whole if statement, I know I'm not fetching the course from anywhere, I just don't know how yet, if there is a better idea/approach please let me know, and thanks for your time.
UPDATE:
Here's a change, this is what I have done so far,
As for the view:
#if ($course->pivot->completed == true)
<button #click.prevent="onSubmit({{ $course }})" type="button" class="btn btn-sm" :id="[isActive ? greenClass.aClass : redClass.aClass]">#{{ greenClass.text }}</button>
{{-- #else
<button #click.prevent="onSubmit({{ $course }})" type="button" class="btn btn-sm" :id="[isActive ? greenClass.aClass : redClass.aClass]"></button> --}}
#endif
Now as for the vue instance:
<script>
new Vue({
el: '#app',
data: {
isActive: true,
greenClass: {aClass: 'coursetogglingtrue', text: 'Done!'},
redClass: {aClass: 'coursetogglingfalse', text: 'Not Yet!'}
},
methods: {
onSubmit: function(course) {
axios.post('/MyCourses/' + course.name)
// .then(function (response){
// });
this.isActive = !this.isActive;
}
}
});
</script>
Since that I know the blade #if condition is passing as true, I can hardcode the is active is true, and when I press on the button I get what I wanted the class actually toggles, if that is not true I default to the other class, now the problem is I need that action to be performed on exactly one button, the one I pressed on, right now what happens is every single button toggles its class, I know that once again it's due to my code not being explicit about this, the thing is I don't know how yet, so please help if you have any idea, have been stuck on this for weeks and weeks, it's really frustrating that I can't get this one simple thing to work.
It doesn’t make sense to put an expression as a property key.
Try this:
new Vue({
el: '#app',
data: {
cssClass: '',
text: ''
},
methods: {
onSubmit: function(course) {
axios.post('/MyCourses/' + course.name)
// .then(function (response){
// });
if (course.completed == true) {
this.cssClass = 'coursetogglingtrue',
this.text = 'Done!'
} else {
this.cssClass = 'coursetogglingfalse',
this.text = 'Not Yet!'
}
}
}
});
I'm playing around with vue.js and the .vue components, and as newbie, I'm wondering how can I keep track of the element I add in the array.
The situation is the following :
The user add a new element from a form
When he submit, the data are automatically added to a ul>li element, and a POST request is made to the API
When the POST is done, I want to update the specific li with the new data from the server.
The thing is, I can not target the last li because the server can take time to process the request (he do a lot of work), so the user may have added 1, 5, 10 other entries in the meantime.
So how can I do ?
Here's my code so far :
<template>
<form method="post" v-on:submit.prevent="search">
<input type="text" placeholder="Person name" required v-model="name" v-el="nameInput" />
<input type="text" placeholder="Company" required v-model="company" v-el="domainInput" />
<input type="submit" value="Search" class="btn show-m" />
</form>
<ul>
<li transition="expand" v-for="contact in contacts">
<img v-bind:src="contact.avatar_url" width="40px" height="40px" class="cl-avatar" />
<div class="cl-user">
<strong class="cl-name">{{contact.name}} <span class="cl-company">{{contact.company}}</span></strong>
</div>
</li>
</ul>
</template>
<script>
export default {
data () {
return {
contacts: [],
name: null,
company: null
}
},
methods: {
search: function (event) {
this.$http.post('/search', {
name: this.name,
company: this.company
}).then(function (xhr) {
// HERE ! How can I target the exact entry ?
this.contacts.unshift(xhr.data)
})
this.name = ''
this.company = ''
this.contacts.unshift({'name': this.name, 'company': this.company})
},
}
}
</script>
Thank you for your help ! :)
If you know that the name and company fields are unique you could search through the array to find it... otherwise you can just wait to append it to the array until the return function:
search: function (event) {
this.$http.post('/search', {
name: this.name,
company: this.company
}).then(function (xhr) {
this.contacts.unshift(xhr.data)
})
this.name = ''
this.company = ''
},
I finally found a working solution : I use a component instead of <li /> for each entries, and manage the state of these inside the component :
<ul>
<contact-entry v-for="contact in contacts" v-bind:contact="contact"></contact-entry>
</ul>
That way, when I add a new entry in the array (described above), a new instance of the component contact-entry is made.
Inside that component, I did the following :
<script>
export default {
props: ['contact'],
created: function () {
if (this.contact.id === undefined) { // If it's a new contact
this.$http.post('search/name', { // I do the post here
name: this.contact.name,
domain: this.contact.company.name
}).then(function (xhr) {
this.contact = xhr.data // This will update the data once the server has replied, without hassle to find the correct line
})
}
}
}
</script>
That's it ! :) In the parent's component, I removed the xhr request and simplified the method to :
<script>
export default {
data () {
return {
contacts: [],
name: null,
company: null
}
},
methods: {
search: function (event) {
this.name = ''
this.company = ''
this.contacts.unshift({'name': this.name, 'company': this.company})
}
}
}
</script>