43

I'm trying to populate a Vue with data from the JsonResult of an AJAX query. My Vue receives the data just fine when I encode it from my View Model, but not when I try to retrieve it using AJAX. Here's what my code looks like:

<script type="text/javascript">

        var allItems;// = @Html.Raw(Json.Encode(Model));

        $.ajax({
            url: '@Url.Action("GetItems", "Settings")',
            method: 'GET',
            success: function (data) {
                allItems = data;
                //alert(JSON.stringify(data));
            },
            error: function (error) {
                alert(JSON.stringify(error));
            }
        });

        var ItemsVue = new Vue({
            el: '#Itemlist',
            data: {
                Items: allItems
            },
            methods: {

            },
            ready: function () {

            }
        });
</script>

<div id="Itemlist">
    <table class="table">
        <tr>
            <th>Item</th>
            <th>Year</th>
            <th></th>
        </tr>
        <tr v-repeat="Item: Items">
            <td>{{Item.DisplayName}}</td>
            <td>{{Item.Year}}</td>
            <td></td>
        </tr>
    </table>
</div>

This is with all of the proper includes. I know that @Url.Action("GetItems", "Settings") returns the correct URL and the data comes back as expected (as tested by an alert in the success function (see comment in success function in AJAX). Populating it like so: var allItems = @Html.Raw(Json.Encode(Model)); works, but the AJAX query does not. Am I doing something wrong?

5
  • 1
    you'll have to update the view's data-items after you've received the data. Note, that ajax is asyncronous (hence the name), so you'll only have data in the success callback function! Commented Sep 5, 2015 at 14:03
  • How can I do that? I can't do ItemsVue.data.Items right? I'm not sure how to update it at that point... Commented Sep 5, 2015 at 14:05
  • I guess I can just create my Vue in the success callback function! Commented Sep 5, 2015 at 14:13
  • sorry, I don't know the API of vue.js, so can't help there. After a quick look at the reference I'd suggest to try: ItemsVue.$data.items=data inside success callback. Commented Sep 5, 2015 at 14:15
  • You'd only have to define the var in the global scope first if you create it in the successcallback Commented Sep 5, 2015 at 14:16

3 Answers 3

83

You can make the ajax call inside of the mounted function (“ready” in Vuejs 1.x).

<script type="text/javascript">
var ItemsVue = new Vue({
    el: '#Itemlist',
    data: {
        items: []
    },
    mounted: function () {
        var self = this;
        $.ajax({
            url: '/items',
            method: 'GET',
            success: function (data) {
                self.items = JSON.parse(data);
            },
            error: function (error) {
                console.log(error);
            }
        });
    }
});
</script>

<div id="Itemlist">
    <table class="table">
        <tr>
            <th>Item</th>
            <th>Year</th>
        </tr>
        <tr v-for="item in items">
            <td>{{item.DisplayName}}</td>
            <td>{{item.Year}}</td>
        </tr>
    </table>
</div>
Sign up to request clarification or add additional context in comments.

5 Comments

See, I tried this. Maybe I was doing something else wrong, I'm not sure.
Isn't that suppose to be self.data.Items = data ?
setting "self" as a reference to the original "this" scope is the key
i am using vuejs 2.0 with mounted. Its work with var self = this; Thanks - @samuel
upvoted! here is a simple question, lets say you have a local field view that is set to A, after ajax data is loaded it should say B, should you change A to B before loading or after loading the data? difference here being if you set A to B before loading, the view changes immediately but the data may or may not render after load but if you change A to B after loading the UI hangs for a second or so until the data is here
2

I was able to solve my problem by performing my necessary action within the success handler on the AJAX call. You can either put the entire Vue object creation in there, or just set the data you need.

2 Comments

@muttley91 Even though this way will work, it doesn't mean is right, certainly this should not be the accepted answer. thanks for post the question.
up voted because there are situations where it makes much more sense to render the vue only after after a set of data calls have completed and all the data has been processed.
2

I had same problem, fixed by Samuel De Backer's answer above.

The problem is at ajax success callback function,

if you use this.data, it is incorrect, because when 'this' reference the vue-app, you could use this.data, but here (ajax success callback function), this does not reference to vue-app, instead 'this' reference to whatever who called this function(ajax call).

So you have to set var self = this before ajax, then pass into callback function (success call back)

Here is my working code

 created () {
     this.initialize()
  },


 mounted () {

        this.getData()
 },


 methods: {

     getData()  {




                 var getUser_url = url + 'cfc/sw.cfc?method=getUser&returnformat=json&queryformat=struct';

                console.log(getUser_url )

            /*
                You can use a plethora of options for doing Ajax calls such as Axios, vue-resource or better yet the browser's built in fetch API in modern browsers. 
                You can also use jQuery via $.ajax() API, which simply wraps the XHR object in a simple to use method call 
                but it's not recommended to include the whole jQuery library for the sake of using one method.


                http://updates.html5rocks.com/2015/03/introduction-to-fetch
                The Fetch API provides a JavaScript interface for accessing and manipulating parts of the HTTP pipeline, such as requests and responses. 
                It also provides a global fetch() method that provides an easy, logical way to fetch resources asynchronously across the network.

            */


                //   **********  must use self = this ************** 
                // this reference vue-app.  must pass it to self, then pass into callback function (success call back)
                var self = this;  


                fetch(getUser_url).then(function (response) {
                                return response.json();
                        }).then(function (result) {

                                 console.log(result);  

                                 // must use self.user,  do not use this.user, 
                                 // because here, this's scope is just the function (result).   
                                 // we need this reference to vue-app, 
                                 self.user = result;  // [{}, {}, {}]  



    }); // fetch(){}


   console.log(this.user);


  }, 



initialize () {}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.