2

I am trying to toggle a span containing a loading animation on a button press until the function completes using v-if. But when I press the button the DOM freezes and the span element is unchanged until the function call ends. How can I make the DOM not freeze and the loading icon to show? Non blocking button press might be a solution?

HTML

    <form class="form-inline">
    <div class="form-group">

        <div style="display: inline-flex" class='input-group date' id='datetimepicker1'>
            <input placeholder="Start Date" id="pick1" type='text' class="form-control"/>
            <span class="input-group-addon">
                <span class="glyphicon glyphicon-calendar"></span>
            </span>
        </div>
    </div>
    <div class="form-group">
        <div style="display: inline-flex" class='input-group date' id='datetimepicker2'>
            <input placeholder="End Date" id="pick2" type='text' class="form-control"/>
            <span class="input-group-addon">
                <span class="glyphicon glyphicon-calendar"></span>
            </span>
        </div>
    </div>
    <div class="form-group">
        <input  class="form-control" type="text" v-model="Keyword" placeholder="keyword">

    </div>

        @*Start Date<input type="text" v-model="StartDate" placeholder="Start Date" style="width: 177px" />
        End Date <input type="text" v-model="EndDate" placeholder="End Date" style="width: 177px" />*@
        <button type="button" v-show="resetShow" class="btn btn-primary btn-lg " v-on:click="reset" id="reset-btn">Reset filters</button>
        <button type="button" v-show="GetShow" type="button" class="btn btn-primary btn-lg " v-on:click="getEdges">Get Edges</button>
        <button   v-show="GetShow" type="button" class="btn btn-primary btn-lg " v-on:click="getNodes">Get Nodes</button>
        <button v-on:click="send" type="button" class="btn btn-default" id="load" >Submit</button>
    <span v-if="loading" id="loader" style="display:none"> <i style="font-size: 197%; color: purple" class='fa fa-circle-o-notch fa-spin'></i> <span style="font-size: 190%"> Processing </span> </span>

Javascript

var vm = new Vue({
el: '#main',
data: {
    resetShow: false,
    Keyword: '',
    StartDate: '2016-06-08T17:03:36.000Z',
    EndDate: '2016-06-16T17:03:36.000Z',
    Dialog: [],
    EdgeList: [],
    NodeList: [],
    loading: false,
    StartDate1: '',
    GetShow: false
},
// define methods under the `methods` object
methods: {

    getById: function(event) {

    },

    send: function(event) {


        this.loading = true;
        console.log(this.StartDate1);
        var StartDate = $('#datetimepicker1').data("DateTimePicker").date().utc().format().split('+')[0]+".000Z";
        var EndDate = $('#datetimepicker2').data("DateTimePicker").date().utc().format().split('+')[0]+".000Z"; 



        if (this.Keyword != null) {

            var g = GetElasticSearch(this.Keyword, StartDate, EndDate);
            s.graph.clear();
            s.graph.read(g);
            sigma.canvas.edges.autoCurve(s);
            s.refresh();
            // Start the ForceLink algorithm:
            sigma.layouts.startForceLink();
            //Louv
            var louvainInstance = sigma.plugins.louvain(s.graph,
            {
                setter: function(communityId) { this.my_community = communityId; }
            });
            var nbLevels = louvainInstance.countLevels();
            console.log(nbLevels);
            var partitions = louvainInstance.getPartitions();
            var nbPartitions = louvainInstance.countPartitions(partitions);
            // Color nodes based on their community
            s.graph.nodes()
                .forEach(function(node) {
                    //console.log(node.my_community);
                    node.color = colors[node.my_community];
                });
            s.refresh({ skipIndexation: true });

            s.graph.nodes()
                .forEach(function(node) {
                    node.color = colors[node.my_community];
                });
            s.refresh({ skipIndexation: true });

            this.loading = true;
        }
    }








}

});

Sepehr Sobhani
  • 862
  • 3
  • 12
  • 29

1 Answers1

6

Vue updates the DOM asynchronously, when the method is finished, so to speak.

So you have to make the part of the function that takes a long tim async, so it does not block the event loop.

You can use setTimeout(callback, 0) to run the function async.

Example: https://jsfiddle.net/Linusborg/tn8q4sub/

(Edit: The example does not always work for me though I don't quite get why that is - give it a try with your situation)

For your code, this should look something like this:

send: function(event) {

  this.loading = true;

  setTimeout(function () {
    //rest of the send code.
    // and at the end:
    this.loading = false
  }.bind(this),0) // the `bind(this)` is important!
}
Linus Borg
  • 23,622
  • 7
  • 63
  • 50
  • running something with timeout of 0 doesnt make a function run async, but rather pauses the JS engine to let the rendering/painting catch up. http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful – nuway Jul 15 '16 at 13:46
  • Uhm... no. You link clearly states: "(In actuality, setTimeout() re-queues the new JavaScript at the end of the execution queue. See the comments for links to a longer explanation." - and re-queeing something at the end of the call stack *is* an async function call. – Linus Borg Jul 15 '16 at 13:52
  • it sure does say that. But I disagree with your notion that "re-queeing something at the end of the call stack is an async function call", since the stack will still be executed in it's latest order, and some blocking might still occur – nuway Jul 15 '16 at 13:59
  • What *would* be an async function call, then? – Linus Borg Jul 15 '16 at 14:05
  • Here, someone actually knowing this inside out uses setTimeout to explain "asychronous callbacks": https://youtu.be/8aGhZQkoFbQ?t=10m35s – Linus Borg Jul 15 '16 at 14:19
  • Ill check it out, man. I don't disagree with you that it achieves async like feature. just not sure if its fair to say that it would "make a function run async", since there are no real async functions in JS, all of this is just faking async – nuway Jul 15 '16 at 14:38