Sepehr Sobhani
Sepehr Sobhani

Reputation: 882

Vue js button freezes dom

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;
        }
    }








}

});

Upvotes: 2

Views: 3377

Answers (1)

Linus Borg
Linus Borg

Reputation: 23988

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!
}

Upvotes: 6

Related Questions