0

I am using SharePoint Online and Vuejs.

I am trying to display a table and in each cell there will be a function call with 2 arguments passed to a method to filter an axios call to a list. When I have the call in one cell it works fine but when I add the call to a different cell with different arguments, my code goes into an infinite loop. I can tell from my developer tool as I see the numbers flashing in the console and on the page. It seems like it calls the method several times for some odd reason and I'm not even using any kind of loop. Here's the code:

Vue.component('msr-table', {
    template: 
    `
        <table>
            <tr>
                <th>LCAT</th>
                <th>Position 1</th>
                <th>Position 2</th>
                <th>Position 3</th>
                <th>Position 4</th>
                <th>Position 5</th>
                <th>Position 6</th>
                <th>Position 7</th>
                <th>Position 8</th>
                <th>Position 9</th>                                                                                
            </tr>
            <tr>
                <td>Operations Research Analyst</td>
                <td>{{ getMsrInputData('Position 1', 'Operations Research Analyst') }}</td>
                <td>{{ getMsrInputData('Position 2', 'Operations Research Analyst') }}</td>
                <td></td>
                <td></td>   
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td> 
            </tr>                 
            <tr>
                <td>Research Analyst</td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>   
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td> 
            </tr>                 
        </table>
    `,
    method: {
        getMsrInputData: function(lName,lCat){                      
            endPointUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbyTitle('Track List')/items?$select=Lists&$filter=substringof('"+ lName +"',%20Lists)%20and%20(mCAT%20eq '"+ mCat +"')";
            var vm = this;
            axios.get(endPointUrl).then(function(response){
                vm.num = response.data.value.length;
                console.log(vm.num);
            }).catch(function(error){
                console.log(error)
            });
            return this.num;                
        },    
    }
})

I've done everything but I just can't figure out why. Any ideas/help would be much appreciated. Thanks!

I just need a single value returned where ever I make a call.

OLA
  • 861
  • 2
  • 11
  • 23
  • Why did you put `return this.num;` outside of the last `then` block? – William Chong Sep 05 '19 at 19:20
  • To return the value to the calling function. Is that wrong? – OLA Sep 05 '19 at 19:23
  • 2
    In this case, your method will return before the axios call is actually finish. You might want to revise on how js promises work. – William Chong Sep 05 '19 at 19:25
  • When I add the return to the first .then() block, nothing gets returned. My understanding is that after the call is complete, the then has my data but the return doesn't work in that block. – OLA Sep 05 '19 at 19:31
  • For a return in the then to work, you will have to return the whole axios call promise in the method, then await it when calling it. In your current code you are returning `this.num` without anyone setting a value to it. – William Chong Sep 05 '19 at 19:36
  • Also in your specific use case, you are better off using vue.js's `data` attribute in your template. The you just call your axios call in `created` or `mounted` hook, sets the corresponding `data` field inside your axios call, then the template will get automatically updated. – William Chong Sep 05 '19 at 19:38

1 Answers1

1

It might be easier for you to use vue.js's data property instead of calling method in the template. Here is a brief untested example to illustrate the idea.

Vue.component('msr-table', {
    template: 
    `
        <table>
            <tr>
                <th>LCAT</th>
                <th>Position 1</th>
                <th>Position 2</th>
                <th>Position 3</th>
                <th>Position 4</th>
                <th>Position 5</th>
                <th>Position 6</th>
                <th>Position 7</th>
                <th>Position 8</th>
                <th>Position 9</th>                                                                                
            </tr>
            <tr>
                <td>Operations Research Analyst</td>
                <td>{{ positionOneData }}</td>
                <td>{{ positionTwoData }}</td>
                <td></td>
                <td></td>   
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td> 
            </tr>                 
            <tr>
                <td>Research Analyst</td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>   
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td> 
            </tr>                 
        </table>
    `,
    data: {
       positionOneData: '',
       positionTwoData: '',
    },
    created() {
        this.getMsrInputData('positionOneData', 'Position 1', 'Operations Research Analyst');
        this.getMsrInputData('positionTwoData', 'Position 2', 'Operations Research Analyst');
    },
    methods: {
        getMsrInputData: function(key, lName,lCat){                      
            endPointUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbyTitle('Track List')/items?$select=Lists&$filter=substringof('"+ lName +"',%20Lists)%20and%20(mCAT%20eq '"+ mCat +"')";
            axios.get(endPointUrl).then((response) => {
                this[key] = response.data.value.length; // this line will update the data
            }).catch(function(error){
                console.log(error)
            });       
        },    
    }
})
William Chong
  • 2,107
  • 13
  • 24
  • I don't get the ```this[key]``` part. Can you elaborate? Is it the same as ```this.positionOneData```? Don't see how that is the same – OLA Sep 05 '19 at 20:46
  • that's the js syntax to use variable (`key` in this case) as object key. see https://stackoverflow.com/a/695053/4899818 – William Chong Sep 05 '19 at 20:51
  • hmmm....so it looks like that works for accessing values in Vue's data property. That's a new one. Thanks! Your solution worked. – OLA Sep 05 '19 at 20:54
  • Ahhhh.....took me a while but I get the ```vm[key]``` now. The data property is an object so that would work. Nice! – OLA Sep 06 '19 at 01:37