Skip to content

Instantly share code, notes, and snippets.

@aghuddleston
Last active August 14, 2016 23:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aghuddleston/73bbf086c3670571b370ada89ccb9182 to your computer and use it in GitHub Desktop.
Save aghuddleston/73bbf086c3670571b370ada89ccb9182 to your computer and use it in GitHub Desktop.
AngularJS 1.3 Sample Directives, Filters and Miscellaneous
<!-- Bootstrap 3 -->
<div>
<div class="modal fade" my-modal id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" ng-click="vm.cancel()"><span aria-hidden="true">&times;</span><span
class="sr-only">Close</span></button>
<h4 class="modal-title" id="myModalLabel">Add New Property</h4>
</div>
<form novalidate class="form-horizontal" role="form" name="newPropForm"
ng-submit="vm.addProperty(newPropForm.$valid)">
<div class="modal-body">
<div ng-show="vm.requestStatus.text" class="alert"
ng-class="{'alert-success': vm.requestStatus.success, 'alert-danger': !vm.requestStatus.success}" role="alert">{{vm.requestStatus.text}}
</div>
<div class="form-group" ng-class="{'has-error': newPropForm.$submitted && newPropForm.addPropEnv.$error.required}">
<label for="newPropEnvSelect" class="col-sm-2 control-label">Environment</label>
<div class="col-sm-10">
<select id="newPropEnvSelect" name="addPropEnv" class="form-control" ng-model="vm.addPropEnv"
ng-options="host.formatted for host in vm.hosts" required>
<option style="display:none" value="">Select an environment</option>
</select>
</div>
</div>
<div class="form-group" ng-class="{'has-error': newPropForm.$submitted && newPropForm.newKey.$error.required}">
<label for="newKey" class="col-sm-2 control-label">Key</label>
<div class="col-sm-10">
<input name="newKey" class="form-control" type="text" id="newKey" placeholder="Key" required
ng-model="vm.prop.key">
</div>
</div>
<div class="form-group" ng-class="{'has-error': newPropForm.$submitted && newPropForm.newValue.$error.required}">
<label for="newValue" class="col-sm-2 control-label">Value</label>
<div class="col-sm-10">
<input name="newValue" class="form-control" type="text" id="newValue" placeholder="Value"
ng-model="vm.prop.value" required>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="vm.prop.encrypted"> Encrypt this value in the database.
</label>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" ng-click="vm.cancel()" class="btn btn-default" >Cancel</button>
<button type="submit" class="btn btn-primary">Add Property</button>
</div>
</form>
</div>
</div>
</div>
</div>
// AngularJS 1.3 directive for an element which is Bootstrap modal to enter new data
.directive('addproperty', [function () {
return {
restrict: 'E',
scope: {
tableLevelMessage: '&'
},
controllerAs: 'vm',
templateUrl: path + '/resources/template/addproperty.html', // path needs to be replaced
controller: ['$scope', 'envService', 'PropFactory', function($scope, envService, PropFactory){
var vm = this;
vm.requestStatus = {};
envService.hosts().then(function (hosts) {
vm.hosts = hosts;
});
this.cancel = function() {
$scope.dismiss();
$scope.newPropForm.$setPristine();
$scope.newPropForm.$setUntouched();
vm.prop = {};
vm.requestStatus = {};
};
this.addProperty = function (valid) {
if(!valid) {
return;
}
vm.prop.encrypted = vm.prop.encrypted || false;
PropFactory.property('add', vm.prop, vm.addPropEnv)
.then(function (response) {
if (response.success) {
$scope.dismiss();
$scope.newPropForm.$setPristine();
$scope.newPropForm.$setUntouched();
$scope.tableLevelMessage({
response: {
success: true,
messageText: 'Data ' + vm.prop.key + ' successfully added. Search to see the new data.'
}});
vm.prop = {};
vm.requestStatus = {};
} else {
vm.requestStatus = {
success: response.status,
text: response.messageText
}
}
}, function(response) {
vm.requestStatus = {
success: response.status,
text: response.messageText
}
});
};
}]
};
}])
<!-- what html looks like in the "parent"
<tr ng-repeat="prop in vm.myProps"
filter-row data="prop" env="vm.searchEnv" table-level-message="vm.showTableMessage(response)"
highlight-text="vm.query"></tr>
-->
<tr>
<td><span ng-bind-html="data.endPoint | highlight:highlightText"></span></td>
<td>
<div ng-if="!data.$edit">{{ data.ipRange }}</div>
<div ng-if="data.$edit">
<input class="form-control input-sm" type="text" ng-model="editData.ipRange" name="iprange">
</div>
</td>
<td>
<div ng-if="!data.$edit">{{ data.portRange }}</div>
<div ng-if="data.$edit">
<input class="form-control input-sm" type="text" ng-model="editData.portRange" name="portrange">
</div>
</td>
<td>
<div ng-if="!data.$edit">{{ data.service }}</div>
<div ng-if="data.$edit">
<service-dropdown service-model="editData.service"></service-dropdown>
</div>
</td>
<td>
<div ng-if="!data.$edit">
<button type="button" class="btn btn-primary btn-sm" ng-click="edit()">Edit</button>
<button type="button" class="btn btn-danger btn-sm" ng-click="delete()">Delete</button>
</div>
<div ng-if="data.$edit">
<button type="button" class="btn btn-success btn-sm" ng-click="save()">Save</button>
<button type="button" class="btn btn-default btn-sm" ng-click="cancel()">Cancel</button>
</div>
</td>
</tr>
// Directive used at the row level in a table. The domain is a "filter", hence the name "filter" in the directive
.directive('filterRow', ['MyFilterFactory', function(MyFilterFactory){
return {
restrict: 'A',
replace: false,
scope: {
data: '=',
env: '=',
highlightText: '=',
tableLevelMessage: '&'
},
templateUrl: path + '/resources/template/filter-row.html', //path should be replaced
link: function(scope, elem) {
scope.editData = {};
scope.edit = function() {
scope.data.$edit = true;
scope.editData = angular.copy(scope.data);
};
scope.cancel = function() {
scope.data.$edit = false;
scope.editData = {};
};
scope.save = function() {
scope.tableLevelMessage({response: {}});
MyFilterFactory.ipfilter('update', scope.editData, scope.env)
.then(function(response) {
if (response.success) {
scope.data = angular.copy(scope.editData);
scope.data.$edit = false;
scope.data.value = scope.editData.encrypted ? "*****" : scope.editData.value;
scope.data.encrypted = scope.editData.encrypted;
scope.editData = {};
} else {
scope.tableLevelMessage({response: response});
}
}, handleHttpError);
};
scope.delete = function() {
scope.tableLevelMessage({response: {}});
MyFilterFactory.myfilter('delete', scope.data, scope.env)
.then(function(response) {
if (response.success) {
elem.remove();
} else {
scope.tableLevelMessage({response: response});
}
}, handleHttpError);
};
elem.on('$destroy', function () {
scope.$destroy();
});
var handleHttpError = function (response) {
scope.tableLevelMessage({response: response});
};
}
};
}])
// AngularJS 1.3
// Directive to close Bootstrap modal
.directive('myModal', function () {
return {
restrict: 'A',
link: function (scope, element, attr) {
scope.dismiss = function () {
$(element).modal('hide');
};
}
}
})
// Directive to add Bootstrap tooltip
.directive('tooltip', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
$(element)
.attr('title', attrs.tooltip)
.tooltip({placement: "bottom"});
}
};
})
// Directive to add sorting to a table with Bootstrap
.directive('simpleSort', ['$compile', function($compile) {
return {
restrict: 'A',
scope: {
currentSort: '=',
sortBy : '@',
sort: '&'
},
link: function(scope, elem, attrs, controller, transclude) {
var template = '<span class="glyphicon rlc" ng-class="sortOrderClass()"></span>',
$template = angular.element(template);
$compile($template)(scope);
elem.append($template);
scope.$watch('currentSort.column', function(sort) {
if (scope.sortBy == sort) {
elem.addClass('sorted');
} else {
elem.removeClass('sorted');
}
});
scope.sortOrderClass = function() {
var cls = '',
sort = scope.currentSort;
if (scope.sortBy == sort.column ) {
cls = sort.descending ? 'glyphicon-chevron-down' : 'glyphicon-chevron-up';
}
return cls;
};
elem.bind('click', function() {
var sort = scope.currentSort;
if (sort.column == scope.sortBy) {
sort.descending = !sort.descending;
} else {
sort.column = scope.sortBy;
sort.descending = false;
}
scope.sort({column: scope.sortBy});
scope.$apply();
});
}
};
}])
// Directive to build a drop-down
.directive('serviceDropdown', function () {
return {
restrict: 'E',
scope: {
serviceModel: '=',
serviceId: '@',
serviceName: '@'
},
template: '<select id="{{serviceId}}" name="{{serviceName}}" class="form-control" ng-model="serviceModel" required> ' +
'<option value="optionOne">Option One</option>' +
'<option value="optionTwo">Option Two</option>' +
'<option value="optionThree">Option Three</option>' +
'<option style="display:none" value="">Select service</option> ' +
'</select>',
link: function(scope, element, attrs) {
console.log(scope);
if (!attrs.serviceId) {
scope.serviceId = "selectService" + scope.$id;
}
if (!attrs.serviceName) {
scope.serviceName = 'selectService' + scope.$id;
}
}
};
})
// AngularJS 1.3
// Filter to highlight text
.filter('highlight', function($sce) {
return function(text, phrase) {
if (phrase) {
text = text.replace(new RegExp('('+phrase+')', 'gi'), '<strong>$1</strong>')
}
return $sce.trustAsHtml(text)
};
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment