Using ng-sortable without ng-repeat

756 Views Asked by At

I have this working example using ng-sortable;

HTML

<ul as-sortable="vm.sortableOptions" ng-model="vm.items">
    <li ng-repeat="item in vm.items" as-sortable-item class="as-sortable-item">
        <div as-sortable-item-handle class="as-sortable-item-handle" style="height: 50px">
            <span data-ng-bind="item.name"></span>
        </div>
    </li>
</ul>

JS

vm.items = [
    { name: 'item 1' },
    { name: 'item 2' }
];

vm.sortableOptions = {
    containment: '#sortable-container'
};

This gives me the result:

Sortable items using ng-repeat

In my case I cannot use ng-repeat since all elements I need sortable have unique and complex HTML content and are not repeatable. For this reason I tried this:

HTML

<ul as-sortable="vm.sortableOptions" ng-model="vm.items">
    <li as-sortable-item class="as-sortable-item">
        <div as-sortable-item-handle class="as-sortable-item-handle">
            <span>Test1</span>
        </div>
    </li>

    <li as-sortable-item class="as-sortable-item">
        <div as-sortable-item-handle class="as-sortable-item-handle">
            <span>Test2</span>
        </div>
    </li>
</ul>

Unfortunately, this gives me the following result: Trying to use ng-sortable without using ng-repeat

The "sortable-items" seems to be "unsortable" if ng-repeat is omitted. Is there any workaround to this? Is it even possible to simply sort x number of divs within one container without using ng-repeat?

2

There are 2 best solutions below

0
On

Ok, so this is how I finally decided to solve my problem, it is not optimal but works.

JS

vm.templates = [
    { url: '/test1.html' },
    { url: '/test2.html' }
];

HTML

<ul as-sortable="vm.sortableOptions" ng-model="vm.templates">
    <li ng-repeat="item in vm.templates" ng-if="item.show" as-sortable-item class="as-sortable-item">
        <div as-sortable-item-handle class="as-sortable-item-handle">
            <div ng-include="'content/scripts/app/templates'+ item.url"></div>
        </div>
    </li>
</ul>

test1.html:

<span>Test1</span>

test2.html:

<span>Test2</span>
2
On

You could take another way, using ng-repeat but looping over your own list of previous ordered components by you of course, where every object in the list could have attributes like type and properties for an individual element. Inside the ng-repeat you could call a directive created by you for inject hmtl code for every element. The example is only for give you a little idea. Hope this help and give you another view point.

html

<div ng-repeat="item in items">
   <div createhtml mid=item.mid data=item.data background=item.background mtitle=item.mtitle>
   </div>
</div>

angularjs

.directive('createhtml', ['$compile',
    function ($compile) {
       return {
             scope:{
                mid:"=",
                data:"=",
                background:"=",
                mtitle:"="
             },
             link: function(scope, element, attr) {
          function createHtmlAtFly(){
             //the html can be as complex as you want
             var htmlStr = "<div type='" + properties.type + "' mid='" + properties.mid+ "' data='" + properties.data + " ' background='" + properties.background "'+ title='" + properties.title +"'>\n" +
    "</div>\n";
           var container = element.find(".divcontainer");
           var toInsert = angular.element(htmlStr);
           container.append(toInsert);
           $compile(toInsert)(scope);
         }
         scope.$watch("data", function (newValue, oldValue) {
            //make element dynamic depending in changes on values in a controller
         }
      }
   }])