Angular Sortable Dynamic Collection

Here’s an example of a sortable (ui-sortable) on a dynamic collection that I’ve worked out. I’ve wrapped this in a custom directive for a collection of widgets that can be re-ordered.

See the Plnkr working example.

Screen Shot

It uses Angular, Bootstrap and ui-sortable. Unfortunately, there is a dependency on jQuery UI Sortable but I don’t see any problems with this example.

Usage

Custom directive


<widget-container class="widget-container"></widget-container>

Directive Template

This is the basic template with the important bits (most of the styling removed). There’s a second directive widget-item embedded to help with the child (collection) items.


<div class="widget-container">
    <button ng-click="widgetContainerCtrl.add()">Add Widget</button>
    <div ui-sortable="widgetContainerCtrl.sortableOptions" ng-model="widgetContainerCtrl.widgets">
      <div widget-item ng-repeat="widget in widgetContainerCtrl.widgets"
        widget="widget"
        data-id="{{widget.id}}" data-pos="{{widget.pos}}">
        <span class="handle">
          <i class="glyphicon glyphicon-move"></i>
        </span>
        <button ng-click="widgetContainerCtrl.remove(widget)">
          <i class="glyphicon glyphicon-trash"></i>
        </button>
        <span>{{widget.id}}</span>
        <span>{{widget.pos}}</span>
        <span>I'm the widget, gotta Love me!</span>
      </div>
    </div>
</div>

We’ve got to be careful with the DOM structure to satisfy ui-sortable — the ng-repeat needs to be directly below ui-sortable.

Directive JavaScript


  var app = angular.module("app", ["ui.sortable"]);
  
  app.directive("widgetContainer", [WidgetContainer]);
  
  function WidgetContainer() {
    return {
      restrict: "E",
      replace: true,
      templateUrl: "widgetContainer.html",
      controller: "WidgetContainerController as widgetContainerCtrl",
      scope: { },
      link: function(scope, element, attrs, ctrl) { }
    };
  }
  
  app.controller("WidgetContainerController", ["$scope", "$timeout", WidgetContainerController]);
  
  function WidgetContainerController($scope, $timeout) {
    var _this = this;
    this.$scope = $scope;
    this.$timeout = $timeout;
    this.widgets = [];
    this.sortableOptions = {
      handle: "< .handle",
      update: function(event, ui) {
        _this.reorder();
      }
    };
  }

  WidgetContainerController.prototype.add = function() {
    // this.widgets.push()
  }
  WidgetContainerController.prototype.remove = function(widget) {
    // this.widgets.splice()
  }
  WidgetContainerController.prototype.reorder = function() {
    // reassign widget.pos
  }

Here’s the child directive:


  app.directive("widgetItem", [WidgetItem]);
  
  function WidgetItem() {
    return {
      restrict: "A",
      scope: {
        widget: "=";
      },
      controller: "WidgetItemController as widgetItemCtrl",
      link: function(scope, element, attrs, ctrl) { }
    };
  }
  
  app.controller("WidgetItemController", ["$scope", WidgetItemController]);
  
  function WidgetItemController($scope) {
    this.widget = $scope.widget;
  }
  WidgetItem.prototype.doSomething = function() { }

Advertisements

jQuery Datepicker With Bootstrap Icon

Update (2014-08-16):
Not using jQuery UI datepicker? See Datepicker With Bootstrap Icon with eternicode’s Bootstrap-datepicker and Bootstrap 3.

The Problem

I recently needed to use the jQuery UI Datepicker but I also wanted to use Bootstrap’s calendar icon. Simple enough, I thought, the datepicker allows me to specify an icon image. Unfortunately, the built-in datepicker option inserts an img tag and it’s not so easy to add a CSS class needed to use a sprite instead.

Continue reading “jQuery Datepicker With Bootstrap Icon”