Thursday, 21 August 2014

UI-Sortable directive not works for the drag sorting between the elements on the first drag or first click when using jquery 2.0.0 in Angular js - Resolved

In this article we are going to see a bug, which is present in the jquery,because of that it affects the Angular ui-sortable directive.now let we see about the sorting between the elements by dragging using angular js, To do this we need following references.


<script type="application/javascript" src="js/jquery-2.0.0.min.js"></script>
<script type="application/javascript" src="js/jquery-ui.min.js"></script>
<script type="application/javascript" src="js/bootstrap.min.js"></script>
<script type="application/javascript" src="js/angular.min.js"></script>
<script type="application/javascript" src="js/angular-ui.min.js"></script>

  
In this sample we take two different kind of sorting elements, one with static element, another with dynamic elements i.e adding elements at runtime using angular js

Code:

       <div style="float: left; margin: 20px">
            <h3>
                static element</h3>
            <ul ui-sortable="sortoptions" class="well" style="width: 400px">
                <li style="" class="well li">LG</li>
                <li style="" class="well li">Samsung</li>
                <li style="" class="well li">Videocon</li>
                <li style="" class="well li">Onida</li>
            </ul>
        </div>

        <div style="float: left; width: 400px; margin: 20px">
            <h3>
                dynamic element</h3>
            <ul id="sortid" ui-sortable="sortoptions" class="well">
                <li class="well alterli" ng-repeat="item in Items">{{item.name}}</li>
            </ul>
        </div>




Output:

Above dynamic element tag not able to drag and sort on first attempt, because of jquery 2.0.0



From the elements, both can be sort using dragging but there is a one issue with the second element, the second rendered elements can't able to drag on the first attempt, but it can drag and sort in second attempt, this issue only occurs in Jquery 2.0.0 when elements are rendered dynamically using ng-repeat. But it works correctly when using Jquery less than or above 2.0.0, This is working correctly for static declared elements Now we are going to see how to fix this issue, to drag the dynamically rendered elements in the first attempt for jquery 2.0.0 version


Why this issue occurs in dynamically rendered elements ?
           When adding the directive ui-sortable to the root tag, that particular element is rendered first,before the rendering of the child elements, because of this behavior drag is fails on the first attempt, it cant able to recognize the event. on the second attempt it success for the dynamic added elements.

How to fix this issue ?

For dynamic rendered elements,  adding a new directive along with ui-sortable directive, add the directive init-sort which i mention before , it will take care remaining things,now your elements are drag and sortable on the first attempt itself.

Directive: 
        samApp.directive('initSort', function ($compile) {
            return {
                restrict: 'A',
                scope: {
                    initSort: '='
                },
                transclude: false,
                link: function (scope, element, attrs) {
                    var firsttime = 0;
                    element.on('mouseover', function () {
                        if (firsttime == 0) {
                            element.sortable("refresh");
                            firsttime = 1;
                            console.log('Triggered');
                        }
                    });
                }
            };
        });



HTML
        <div style="float: left; width: 400px; margin: 20px">
            <h3>
                dynamic element</h3>
            <ul id="sortid" ui-sortable="sortoptions" init-sort class="well">
                <li class="well alterli" ng-repeat="item in Items">{{item.name}}</li>
            </ul>
        </div>



Output:



Full Code:
HTML 


<body ng-app="samApp">
    <div ng-controller="sampleController">

        <div style="float: left; margin: 20px">
            <h3>
                static element</h3>
            <ul ui-sortable="sortoptions" class="well" style="width: 400px">
                <li style="" class="well li">LG</li>
                <li style="" class="well li">Samsung</li>
                <li style="" class="well li">Videocon</li>
                <li style="" class="well li">Onida</li>
            </ul>
        </div>

        <div style="float: left; width: 400px; margin: 20px">
            <h3>
                dynamic element</h3>
            <ul id="sortid" ui-sortable="sortoptions" init-sort class="well">
                <li class="well alterli" ng-repeat="item in Items">{{item.name}}</li>
            </ul>
        </div>

    </div>
    <script type="application/javascript" src="js/jquery-2.0.0.min.js"></script>
    <script type="application/javascript" src="js/jquery-ui.min.js"></script>
    <script type="application/javascript" src="js/bootstrap.min.js"></script>
    <script type="application/javascript" src="js/angular.min.js"></script>
    <script type="application/javascript" src="js/angular-ui.min.js"></script>
    <script type="application/javascript" src="ang/samApp.js"></script>


</body>


Angular JS

        /**
        * Created by Rajesh on 20-08-2014.
        */

        var samApp = angular.module('samApp', ['ui']);

        samApp.controller('sampleController', function ($scope) {

        $scope.Items = [
                   { name: 'Rajesh' },
                   { name: 'Suresh' },
                   { name: 'Aneesh' },
                   { name: 'Gokul' }
             ];

            
        $scope.sortoptions = {
                update: function (event) {

                },
                stop: function (e, ui) {
                    console.log('stop item', ui.item.scope());
                    console.log('stop item', ui.item.sortable);
                    var item = ui.item.sortable.moved;
                    var fromIndex = ui.item.sortable.index;
                    var toIndex = ui.item.sortable.dropindex;
                    console.log(item, fromIndex, toIndex, $scope.dropTarget);
                },
                start: function (e, ui) {
                    console.log('start item', ui.item.scope());
                }
            };



        });

        samApp.directive('initSort', function ($compile) {
            return {
                restrict: 'A',
                scope: {
                    initSort: '='
                },
                transclude: false,
                link: function (scope, element, attrs) {
                    var firsttime = 0;
                    element.on('mouseover', function () {
                        if (firsttime == 0) {
                            element.sortable("refresh");
                            firsttime = 1;
                            console.log('Triggered');
                        }
                    });
                }
            };
        });




From this post you can see how to drag the elements in the first attempt when JQuery is 2.0.0.