angoose
Version:
Angoose is a Remote Method Invocation module that comes with built-in mongoose/angular support. Now you can call server side module in browser just like you're in the server side!
213 lines (185 loc) • 9.64 kB
JavaScript
(function(){
angular.module('angoose.ui.directives').directive("deformListing", angList ).directive("angList", angList);
function angList( $templateCache, $routeParams, $compile, $location, $injector, MessageBox, $log ,$route, $ui, $controller, angoose){
// this is the main controller for the sort-paging-filtering list
var directive = {
restrict:'AE'
};
directive.controller = function($scope){
var query = $scope.defineQuery();
this.refresh = function(){
query.update(null, true);
}
};
directive.compile = function(element, attrs){
angoose.logger.trace("In ang-list compile");
var preLink = function($scope, $element, $attrs){
/** we do this in prelink because child directives needs the dmeta setup below */
enterscope($scope, "ang-list prelink", $route.current);
/**@todo: calling custom controller here is kinda not the right angular way, but we augment the $scope */
// get the configured defaults
// var ctrl = $ui.getConfig($location.path());
// if(ctrl){
// console.log("Calling user defined controller", ctrl)
// $controller ( ctrl, {$scope: $scope, $element:$element, $attrs: $attrs});
// }
// if($routeParams.customController) {
// $controller ( ($routeParams.modelName+"-list-"+ $routeParams.customController).toLowerCase(), {$scope: $scope});
// }
var dmeta = $scope.defineQuery();
// $scope.dmeta = $scope.dmeta || {};
// var dmeta = $scope.dmeta;
/** order or presedence: custom controller -> directive -> route params */
dmeta.modelName = dmeta.modelName || $attrs.modelName || $routeParams.modelName ;
try{
dmeta.modelClass = $injector.get($ui.camelcase( dmeta.modelName ));
}
catch(err){
console.error("Error in deformListing controller", err)
MessageBox.error("Model "+ dmeta.modelName+" is not defined")
return;
}
// publish it to the parent scope
var listName =$attrs.angList || $ui.apiCamelcase( dmeta.modelName ) + "List";
if($scope.$parent)
$scope.$parent[listName] = dmeta;
else
$scope[listName] = dmeta;
dmeta.pageTitle = dmeta.pageTitle || $ui.camelcase(dmeta.modelName) + " List"
dmeta.actionColumn = dmeta.actionColumn === undefined ? true: dmeta.actionColumn;
if(Array.isArray(dmeta.columns) && dmeta.columns.length > 0){
var cols = [];
for(var i=0;i< dmeta.columns.length;i++){
var item = dmeta.columns[i];
var pathname = typeof(item) == 'string'? item: item.path;
var original = $ui.getPathSchema(dmeta.modelClass, pathname);
if(typeof(item) == 'object')
item = angular.extend( angular.extend({}, original), item)
else
item = original;
if(!item) item = {path: pathname, options: {sortable:false } }
cols.push( item );
}
dmeta.columns = cols;
}
else
dmeta.columns = findTagged(dmeta.modelClass, 'default-list');
//dmeta.spec = dmeta.spec || { filter:{} }
var spec = dmeta.spec;
// controller -> directive
if(!spec.preset && $attrs.defaultFilter)
spec.preset = $scope.$eval($attrs.defaultFilter);
var defaultSortField = getDefaultSortField(dmeta.modelClass) ;
//controller -> directive -> default
spec.sortBy = spec.sortBy || ($attrs.defaultSort? $attrs.defaultSort : '');
spec.sortBy = spec.sortBy || ( defaultSortField? defaultSortField.path: '' );
spec.sortDir = spec.sortDir || ($attrs.sortDir?$attrs.sortDir:'');
spec.sortDir = spec.sortDir || (defaultSortField? defaultSortField.options.defsort: 'asc');
//console.log($scope.dmeta.columns, " ### COLOUMNS" )
$scope.remove = function(index){
//MessageBox.warn("This will delete "+ $scope.instances[index].getDisplayName() +", please confirm");
MessageBox.confirm("This will delete selected item, continue?", function(){
$scope.instances[index].remove( function(err,res){
if(!err){
MessageBox.success("Operation Successful");
$scope.instances.splice(index, 1);
}
} );
}, function(){
})
}
$ui.resolveAndCompile($scope, $element, $attrs, dmeta, 'deform.list.tpl');
//
// $ui.resolveTemplate(element, $attrs, dmeta, 'deform.list.tpl').then(function(em){
// console.log("Resolved template, compiling(default: list.tpl')", em)
// if(em){
// $element.html("<!-- CLEARED -->"); // first clear the inline template
// $element.append(em);
// $compile(em)($scope);
// }
// }, function(err){
// console.error("Error resolving template(list.tpl)", err);
// });
}
var postLink = function($scope, $element, $attrs){
enterscope($scope, "postlink ang listing");
var spec = $scope.dmeta.spec;
$scope.$watch("dmeta.spec", function(newVal, oldVal){
angoose.logger.trace("Filter changed", newVal, oldVal);
// handles the search fields, we need to make a copy of the search filters so that it won't trigger the $watch
var mQuery = angular.extend({}, spec.filter);
if(spec.preset)
mQuery = angular.extend(mQuery, spec.preset); // preset filter takes presedence
angular.forEach(mQuery, function(val, key){
if(val === '$CLEAR$')
delete mQuery[key];
});
var mSelection = null; //@TBD
var mOptions = {}; // limit, skip, sort
if(spec.sortBy){
mOptions.sort = (spec.sortDir && spec.sortDir.toLowerCase() == 'desc')? "-":"";
mOptions.sort += spec.sortBy;
}
if(spec.pageSize) {
mOptions.limit = spec.pageSize;
if(spec.page > 1)
mOptions.skip = (spec.page-1) * spec.pageSize
}
angoose.logger.trace("Updating search: ", mQuery ,mOptions, $scope.dmeta.modelName);
$scope.instances = $scope.dmeta.modelClass.$query(mQuery, mSelection, mOptions )
$scope.dmeta.modelClass.count(mQuery).done(function(total){
//if(err) $log.error("Error getting total. Query: ", mQuery, " Error:", err);
spec.$total = total || 0;
});
}, true);
$scope.cells = [];
// var templateUrl = $attrs.templateUrl;
// if(!templateUrl && !element.html()){
// templateUrl = "deform.list.tpl"; // default
// }
// if(templateUrl){
// element.html("<!-- to be replaced by contents from "+ templateUrl+" -->");
// console.log("Loading templateUrl", templateUrl);
// $ui.loadTemplate(templateUrl).then(function(em){
// console.log("Compiling template ", em);
// element.append(em);
// $compile(em)($scope);
// }, function(er){
// console.log("Failed to load template", templateUrl)
// })
// }
// $compile template if provided
// var template = getTemplate(scope.data);
// element.html(template);
//
} // end link
return {pre:preLink, post:postLink }
}; // end compile
return directive;
}; // end directiveFunc
// get a list of fields with a specific tag
function findTagged(modelClass,tag){
if(!modelClass || !modelClass.schema) return [];
var cols = [];
Object.keys(modelClass.schema.paths).forEach(function(path){
var data = modelClass.schema.paths[path];
if(data.options.tags && data.options.tags.indexOf(tag)>=0)
cols.push(data);
});
return cols;
}
function getDefaultSortField(modelClass){
if(!modelClass || !modelClass.schema) return [];
var ret = null;
Object.keys(modelClass.schema.paths).forEach(function(path){
var data = modelClass.schema.paths[path];
if(data.options.defsort && typeof(data.options.defsort) == 'string')
ret = data;
});
return ret;
}
})(); // scope wrapper
function enterscope(scope, name, arg1) {
angoose.logger.trace("Entering scope ", name, scope.$id, arg1)
window['scope' + scope.$id] = scope;
}