AngularJS Tutorial: Twin List Directive

Leave a comment Standard

Do you have really long select lists that make it hard for users to select multiple options? This twin list directive may solve your problems (well, not the ones in your head hehe) and it’s really easy to use and implement. This requires the underscore library so YAY! no jquery.

View, edit or fork it on Plunker

Create The Index File

So this is pretty simple. All we’re going to do is create a file and give it the ng-app tag with the name of our application then add our new twinList directive. One attribute is for the data they can add to the selection box and the other attribute is for the data they’ve selected. If you want some values selected by default then add them into whatever variable you’re using for your selected data.

<!DOCTYPE html>
<html ng-app="design1online">
 <head>
 <link data-require="bootstrap@*" data-semver="3.3.5" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
 <link data-require="bootstrap@*" data-semver="3.3.5" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" />
 http://code.jquery.com/jquery-2.1.4.min.js
 //maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js
 //maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.js
 https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js
 //cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js
 <link rel="stylesheet" href="style.css" />
 http://controller.js
 http://twinList.js
 </head>
 <body ng-controller="dataList">
 <section>
 <h1 class="text-center">Twin Lists Angular Directive</h1>
 <twin-list data="listData" selected="selectedData"></twin-list>
 </section>
 <section>
 <h4 class="text-center">Retrieving The Directive Data</h4>
 <p>Use the elements you're passing to the directive attributes:</p>
 <p>Unselected: {{listData}}</p>
 <p>Selected: {{selectedData}}</p>
 </section>
 </body>
</html>

Create The Controller

Now that we have our twin list directive on the page we need to create a controller for our angular app. In in we can pre-populate the values for our listData and our selectedData. These are the default values that will show up in our twin list directive when it loads.

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

design1online.controller('dataList', function($scope) {
 $scope.listData = [];
 $scope.selectedData = [];
 
 var maxOptions = 30;
 var multiplesOfTen = 10;
 
 for (var i = 0; i < maxOptions; i++) {
 $scope.listData.push(i);
 
 //select some stuff
 if (i % multiplesOfTen === 0) {
 $scope.selectedData.push(i);
 }
 }
});

Add The Directive File

Now we add the file for the twin list. If you want the layout file you’ll have to a check the plunker because wordpress is doing some kind of weird regex on the code and won’t display it 😦

The Directive File

design1online.directive('twinList', function() {
 return {
 restrict: 'E',
 scope: {
 data: '=data',
 selected: '=selected'
 },
 link: function (scope, element) {
 scope.data = _.difference(scope.data, scope.selected);
 },
 templateUrl: function() {
 return 'twinList.html';
 },
 controller: function($scope) {
 
 function sort(data) {
 return _.sortBy(data, function(num){ return num; });
 }
 
 $scope.addSelected = function() {
 $scope.selected = sort(_.union($scope.dataSet, $scope.selected));
 $scope.data = sort(_.difference($scope.data, $scope.dataSet));
 }
 
 $scope.removeSelected = function() {
 $scope.data = sort(_.union($scope.selectedSet, $scope.data));
 $scope.selected = sort(_.difference($scope.selected, $scope.selectedSet));
 }
 
 $scope.selectAll = function() {
 $scope.selected = sort(_.union($scope.selected, $scope.data));
 $scope.data = [];
 }
 
 $scope.deselectAll = function() {
 $scope.data = sort(_.union($scope.selected, $scope.data));
 $scope.selected = [];
 }
 },
 }
});