Birdy Birdy - 29 days ago 15
Ajax Question

binding ajax response to vue.js (multiple requests on single page)

After a few days researching Vue.js and how it can interact with laravel i have come to a grinding holt and i am starting to wonder two things: One is im just not good enough with my knowledge to continue with my desire to enhance our user experience or two: its not possible to do what i am trying to do so hopefully someone with greater knowledge can help me overcome my road block.

Please forgive my rather basic mock-up!

My very basic mock example of how the request currently works!

Everything works fine as far as jquery / Ajax is concerned however i have tried to move over to vue.js and that's when things are not running to smoothly.

I have the Ajax request working fine however when ever i use this.$set or this.$http for the get or post request i get this message:

11:14:28.690 TypeError: this.$http is undefined 1 vue:61:21
window.onload/queryAPI http://me.dev/vue:61:21
window.onload/ajaxVm<.methods.callAjax http://me.dev/vue:55:29
n http://me.dev/newjs/vue.js:6:836
G/< http://me.dev/newjs/vue.js:6:6272

11:24:21.000 TypeError: this.$set is not a function 1 vue:34:29
window.onload/queryAPI/<.success http://me.dev/vue:34:29
jQuery.Callbacks/fire http://code.jquery.com/jquery-3.1.1.js:3305:11
jQuery.Callbacks/self.fireWith http://code.jquery.com/jquery-3.1.1.js:3435:7
done http://code.jquery.com/jquery-3.1.1.js:9242:5
.send/callback/< http://code.jquery.com/jquery-3.1.1.js:9484:9


My full testing document:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="//code.jquery.com/jquery-3.1.1.js"></script>
<script type="text/javascript" src="/newjs/vue.js"></script>

<title>VueJS</title>
<script type='text/javascript'>//<![CDATA[
window.onload=function(){
var ajaxVm = new Vue({
el:'#test',
data:{
User:{
Name: 'John Doe'
},
datas: 'Hi'
},
methods:{
callAjax: function(e){
queryAPI();
}
}
});

var queryAPI = function(){
this.$http.post('/vue/ajax', this.formData).then(function(response) {
console.log(response);
}, function() {
console.log('failed');
})
}
}
</script>
</head>
<body>
<div id="test">
<label id="data">@{{datas}}</label>
<label>@{{User.Name}}</label>
<br/>
<button v-on:click="callAjax">
Call Ajax
</button>
</div>
</body>
</html>


And with ajax/jquery as apose to this.$http it works fine apart from this.$set as i have to revert to using jquery to update the element.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="//code.jquery.com/jquery-3.1.1.js"></script>
<script type="text/javascript" src="/newjs/vue.js"></script>
<title>VueJS</title>
<script type='text/javascript'>//<![CDATA[
window.onload=function(){
var ajaxVm = new Vue({
el:'#test',
data:{
User:{
Name: 'John Doe'
},
datas: 'Hi'
},
methods:{
callAjax: function(e){
queryAPI();
}
}
});

var queryAPI = function(){
$.ajax({
url: '/vue/ajax',
type: 'POST',
dataType: 'json',
data: ajaxVm.$data ,
success:function(data){
$('#data').html(data.Message);
console.log(data);
//this.$set('datas', data.Name)
},
error:function(xhr,text,exception){
console.error(exception);
}
})
}
}
</script>
</head>
<body>
<div id="test">
<label id="data">@{{datas}}</label>
<label>@{{User.Name}}</label>
<br/>
<button v-on:click="callAjax">
Call Ajax
</button>
</div>
</body>
</html>


I have both vue.js 2.0.5 and vue-resource 1.0.3 included and I have tried using npm with gulp to a single .js file and I've also tried to include them individually via cdn and no matter how I do it I still get the errors when using this.$http or this.$set, I'm starting to wonder if its vue-resource related? IS there any other way I can bind my ajax call to an element or component, I have no clue what so ever what I can not get the thing working as should, Everything seems to be put together correctly and I have read through endless other vuejs related questions but everything is limiting when your knowledge is somewhat little.

Thanks, I will be extremely grateful for any advice on this as its driving me insane!

Answer

This looks like a scope issue. When using this.$http this must refer to the Vue instance, You cannot call $set or $http with this outside of the Vue instance, so you need to place your ajax request inside the view model:

var ajaxVm = new Vue({
    el:'#test',
    data:{
        User:{
            Name: 'John Doe'
        },
        datas: 'Hi'
    },
    methods:{
        callAjax: function(e){
           // Now this refers to the Vue instance
           this.$http.post('my-url',this.data).then((response) => {
                // Response logic here
           })
        }
    }
});

When you do the following, this refers to the enclosing function:

var queryAPI = function(){
  //here this refers to queryAPI, not vue
}

To call $http from outside the view model you need to reference the Vue instance directly:

var queryAPI = function(){
                // Now we are calling $http from the "ajaxVm" vue model instance
                ajaxVm.$http.post('/vue/ajax', this.formData).then(function(response) {
                    console.log(response);
                }, function() {
                    console.log('failed');
                })
            }

Also remember that anything wrapped inside a function creates it's own reference to this unless you use an arrow function (these exmaples assume that you have placed you code inside a Vue instance):

this.$http.get('/foo').this(function(response){
      // here this only refers to the function, not the Vue instance
});

With an arrow function found in ECMA6:

this.$http.get('/foo').this((response) =>{
      // Because we used an arrow function, no new context is created
      // so this refers to the Vue instance
});