0) Estructura de controladores

ComponentCtrl
function ComponentCtrl($scope, $location, DataDefinition){ ... };

function SubComponentCtrl($scope, $location, DataDefinition) {
  ComponentCtrl.call(this, $scope, $location, DataDefinition);
  ...
};

SubComponentCtrl.prototype = Object.create(ComponentCtrl.prototype);

app.controller("SubComponentCtrl", SubComponentCtrl);
ComponentModalCtrl
function ComponentModalCtrl($scope, $uibModalInstance, $timeout, DataDefinition, params){ ... }

function SubComponentModalCtrl($scope, $uibModalInstance, $timeout, DataDefinition, params){
  ComponentModalCtrl.call(this, $scope, $uibModalInstance, $timeout, DataDefinition, params);
}
      
SubComponentModalCtrl.prototype = Object.create(ComponentModalCtrl.prototype)

app.controller('SubComponentModalCtrl', SubComponentModalCtrl);

1) Leer parámetros

Ejemplo: Lectura básica de parámetros utilizando el servicio $location
$scope.params = $location.search();
Ejemplo: Lectura de parámetros particulares
 $scope.setParams = function(){
    var s = $location.search()
    for (var param in s) {
      if(s.hasOwnProperty(param)) {
        if(param == "search") {
          $scope.config.comision.search = s["search"];
        } else {
          $scope.params[param] = s[param]
        }
      }
    }
  }  

  $scope.setParams();//llamamos al metodo de lectura de parámetros
Ejemplo: Lectura de “search identification”

Si está definido el parámetro sid, se toman sus valores ignorando el resto de los parametros

$scope.setConfig = function(cmp){
    var params = $scope.params;
    var filter = [];
    if("sid" in $scope.params) params = JSON.parse($scope.params["sid"]);      
       
    for(var i in params){
      if(params.hasOwnProperty(i)){
        if(!(i in $scope.config[cmp])) $scope.config[cmp].filter.push({field:i, option:"=", value:params[i]})
        else $scope.config[cmp][i] = params[i];                     
      }      
    }  
  };

$scope.setConfig("asignatura"); //Definir configuración del componente principal

2) Definir variables de configuración

Ejemplo: Definir variables básicas
$scope.disabled = true; //Flag para indicar si el componente esta habilitado o no

$scope.message = null; //Mensaje al usuario

$scope.options = {carga_horaria:[]}; //Opciones

$scope.comision = {}; //Datos de row

$scope.curso_ = []; //Datos de un conjunto de rows.

$scope.config = {//Configuración de subcomponentes
    comision:{entity:"comision", sync:{}},
    curso_:{
      entity:"curso", maxQuantity:null, sync:{comision:false}, errorQuantity:false,
      modal:{template:"component/AdminModal/_Curso/Template.html", controller:"CursoAdminModalCtrl"},
      params:null,  
    }
  }
Ejemplo: Configuración de componente para un conjunto de rows que utiliza filtros de búsqueda
  $scope.config = {
    asignatura_:{
      entity:"asignatura", sync:{}, pages:null, export:null,
      modal:{controller:"AsignaturaAdminModalSimpleCtrl", template:"component/AdminModal/AsignaturaSimple/Template.html" },
      size:"10", page:1,  search:null, filter:[], filter_:[], params:[], order:[] //configuracion variable      
    }
  }
Ejemplo: Configuración de componente para un conjunto de rows para administración
toma_:{
      entity:"toma", minQuantity: false, maxQuantity:false, sync:{curso:false}, errorQuantity:null,
      params:null, 
    }

3) Inicializar componente

Ejemplo: Ejemplo básico de definición de datos
  $scope.$on('$viewContentLoaded', function(event) { $scope.setData(); });

  $scope.setData = function(){
     DataDefinition.initializeExtend({entity:"curso", params:$scope.params}).then(
       $scope.curso = responses["cmp"].row;
       return $scope.setToma_($scope.curso.id.value);                            
     );     
  }

  $scope.setToma_ = function(curso){
    $scope.config["toma_"].params = {curso:curso};
    return DataDefinition.initializeFieldsetRows({entity:"toma", params:{curso:curso}}).then(
      function(response){ 
        $scope.toma_ = response.rows; 
        return response;
      }
    )
  };
Ejemplo: Ejemplo básico de definición de opciones
  $scope.$on('$viewContentLoaded', function(event) { $scope.initComponent(); });

  $scope.setOptions(){
    var promises = {
      opt_e: DataDefinition.rowsLabel({entity:"estado"}),
      opt_ch: DataDefinition.rowsLabel({entity:"carga_horaria"}),      
    }

    return DataDefinition.q.all(promises).then(
       function(responses){
         $scope.options.carga_horaria = responses["opt_ch"].rows;
         $scope.comision = responses["cmp"].row;
       }
     );     

  }

  $scope.initComponent(){
    $scope.setOptions().then(){
      function(response){ return $scope.setData(); }
    }
  }

  
  $scope.setData = function(){ ... };  
Ejemplo: Definición de “search identification”

1) Al inicializar, se leen los parámetros y se llama a $scope.setData
2) Al buscar se llama a $scope.setSid para redefinir los parámetros en la url y rutear, al rutear se repite el paso descripto en el punto 1.

  $scope.$on('$viewContentLoaded', function(event) { $scope.initComponent(); });

  $scope.initComponent = function(){ $scope.setData(); };

  $scope.setData = function(){ ... acceso al servidor para obtener datos... }

  $scope.setSid = function(cmp){
    var cfg = $scope.config[cmp];
    var sid = JSON.stringify({size:cfg["size"], page:cfg["page"], search:cfg["search"], filter:cfg["filter"], params:cfg["params"], order:cfg["order"]});
    $location.search('sid',sid); 
  }
Ejemplo: Inicialización de relaciones

administrador.persona m:u id_persona.id
id_persona.id u:u_ usuario.persona

  $scope.config = {
    administrador:{entity:"administrador", sync:{id_persona:false}},
    id_persona:{entity:"id_persona", sync:{}},
    usuario:{entity:"usuario", sync:{persona:false}, add:false}
  }
  
  $scope.administrador = {};
  $scope.id_persona = {};
  $scope.usuario = {};


  $scope.setData = function(){
    return $scope.initializeAdministrador().then(
      function(response){ 
        var prP = $scope.initializeIdPersona(response.persona.value)
        var prU = $scope.initializeUsuario(response.persona.value)
        
        return DataDefinition.q.all([prP, prU]);
      }
    );
  };


  $scope.initializeAdministrador = function(){
    return DataDefinition.rowById({entity:"administrador", id:$scope.id}).then(
      function(response){
        response.row = $scope.setRowParams(response.row);
        return DataDefinition.rowFieldset(response).then(
          function(response_){
            $scope.administrador = response_.row;
            return response_.row;
          }
        );      
      }
    );
  }

  
  $scope.initializeIdPersona = function(idPersona){
    return DataDefinition.rowById({entity:"id_persona", id:idPersona}).then(
      function(response){
        if(!response.row) response.row = {};
        return DataDefinition.rowFieldset(response).then(
          function(response_){ 
            $scope.id_persona = response_.row;
            return response_;
          }
        );      
      }
    );
  }
  
  $scope.initializeUsuario = function(idPersona){
    return DataDefinition.rowByUnique({entity:"usuario", params:{persona:idPersona}}).then(
      function(response){
        if(!response.row) response.row = {};
        return DataDefinition.rowFieldset(response).then(
          function(response_){ 
            $scope.usuario = response_.row;
            if(response_.row.id.value) $scope.config["usuario"].add = true;
          }
        );      
      }
    );
  }

4) Chequear y procesar datos

Ejemplo: chequeo y procesamiento básico
  //Enviar formulario  (metodo generico)
  $scope.submit = function(){ 
    $scope.disabled = true;
    $scope.message = "verificando";
    $scope.checkComponents();
  };

  //Chequear datos (metodo generico)
  $scope.checkRow = function(component){
    return DataDefinition.rowCheck({entity:$scope.config[component].entity, row:$scope[component], sync:$scope.config[component].sync}).then(
      function(response){
        $scope.setErrors(component, response.errors);       
        return response;
      }
    );
  };

  //Chequear componentes (componente principal)
  $scope.checkComponents = function(){
    $scope.checkRow("asignatura").then(
      function(response){
        if(response.checked) $scope.processComponents();
        else $scope.error();
      },
      function(error) { $scope.die(error.data); }
    );       
  };

  //Procesar componentes (componente principal)
  $scope.processComponents = function(){
    return DataDefinition.persistRowExtend({entity:"asignatura", row:$scope["asignatura"], transaction:$scope.transaction}).then(
      function(response){ $scope.processTransaction(); },
      function(error) { $scope.die(error.data) }   
    );
  };

  //Procesar transaccion (metodo genérico)
  $scope.processTransaction = function(){
    DataDefinition.processTransaction($scope.transaction).then(
      function(response){
        $scope.message = "guardado";    
        $scope.alert({title:"Registro realizado", message:"Los datos han sido cargados"});
      },
      function(error){ $scope.die(error.data); }
    );
  };

5) Filtro de búsqueda avanzada

Ejemplo: Inicialización del template de filtro de búsqueda

Se inicializa una variable auxiliar al filtro para visualizar los datos correctamente.
Si se da la opción de modificar el filtro, se asigna valor al filtro auxiliar, al instante se formatea dicho valor y se asigna al filtro real.

Componente principal

  $scope.setFilter = function(cmp){
    DataDefinition.initFilter($scope.config[cmp]).then(
      function(response){ $scope.config[cmp].filter_ = response.filter; }            
    );
  };

Subcomponente de administración de búsqueda

  $scope.changeField = function($index){
    $scope.config.filter_[$index].option = null;
    $scope.config.filter_[$index].value = null; 
    $scope.filterConfig()
  };
  
  
  $scope.filterConfig = function(){
    $scope.config.filter = [];
    DataDefinition.serverFilter({entity:$scope.config.entity, filter:$scope.config.filter_}).then(
      function(response){ 
        console.log(response);
        $scope.config.filter = response.filter; 
      }
    );
  };