I'm wrapping ui-select in my own directives to pre-configure and style it, as I need it for my app in different select widgets. They appear on many pages, for example accountSelect
, countrySelect
, contactSelect
and so on.
What I really dislike is, that I'm mostly copy-and-pasting the directive's code and then just changing the service. What I would normally do is to create some kind of abstract or base class and inherit from that but classes and inheritance are a "problem" in Javascript for me. By the way, I'm aware the language is prototypical. So far I couldn't find a better way to avoid the code duplication between the directives.
Any recommendation how to make this more DRY?
angular.module('crm.invoicing').directive('productsSelect', [function() {
return {
restrict: 'E',
scope: {
productId: '=',
products: '=',
multiple: '=?',
onSelection: '=?',
onRemoval: '=?',
selectOptions: '=?',
list: '=?'
},
transclude: true,
templateUrl: '/psa/invoicing/templates/products-select.html',
controller: function($scope, ProductsService) {
$scope.multiple = angular.isDefined($scope.multiple) ? $scope.multiple : false;
if (!angular.isDefined($scope.selectOptions)) {
$scope.selectOptions = {};
};
var data = {
productId: $scope.productId,
products: $scope.products,
items: null,
selected: $scope.products
};
if ($scope.multiple === false) {
data.items = [data.selected]
} else {
data.selected = $scope.products;
data.items = []
}
$scope.productsList = {
items: data.items,
selected: data.selected,
select: function ($item, $model) {
$scope.productsList.selectedItem = $item;
if ($scope.multiple === false) {
if ($item !== undefined) {
$scope.productId = $item.id;
}
} else {
for (var i = 0; i < $scope.data.products.length; i++) {
if ($scope.data.products[i].id == $item.id) {
return;
}
}
$scope.data.products.push($item);
}
if ($scope.onSelection) {
$scope.onSelection($item, $model, $scope.productsList);
}
},
remove: function($item, $model) {
if ($scope.multiple === false) {
} else {
for (var i = 0; i < $scope.data.products.length; i++) {
if ($scope.data.products[i].id == $item.id) {
$scope.data.products.splice(i, 1);
}
}
}
if ($scope.onRemoval) {
$scope.onRemoval($item, $model, $scope.productsList);
}
},
search: function(term) {
if (term.length > 2) {
ProductsService.lookup(term).then(function(result) {
if ($scope.multiple === false) {
} else {
for (var i = 0; i < $scope.data.products.length; i++) {
for (var i2 = 0; i2 < result.data.length; i2++) {
if (result.data[i2].id == $scope.data.products[i].id) {
result.data.splice(i2, 1);
}
}
}
}
$scope.productsList.items = result.data;
});
}
}
};
angular.extend($scope.productsList, $scope.selectOptions);
if (angular.isDefined($scope.list)) {
$scope.list = $scope.productsList;
}
}
};
}]);