[SOLUCIONADO] Consultas sobre ei_formulario_ml

Hola, tengo varias consultas sobre este componente:

1)
tengo definido el análisis en línea, y el mecanismo definido como Evento Javascript y no puedo capturar el evento pedido_registro_nuevo. La idea sería limitar la cantidad de líneas agregadas. Más allá de poder definirlo en el Editor, quiero capturar el “error” del usuario mientras está cargando los datos.


function evt__formulario_emails__pedido_registro_nuevo()
{
	if ($this->dep('formulario_emails')->get_cantidad_lineas() > 3) {
		throw new toba_error('No pueden ingresarse más de 3 emails.');
	} else {
		$this->get_relacion()->tabla('docentes_emails')->set_registro_nuevo(array('email' => 'a@a.com', 'predeterminado' => false));
	}
}

2)
De la misma forma y relacionado con el punto anterior, para este caso, y otros, no puedo asignar valores por defecto dinámicos a las filas.

3)
El código que adjunto proviene de una operación muy similar al ABM de Personas del proyecto de referencia.
Es un ABM de Personas, que a su vez, tienen varios emails que se cargan en una pantalla aparte a través de un form_ml.
Los datos que tiene la tabla personas_emails son, id, id_persona, email, predeterminado. Este último es un campo booleano que representará al email de los que posee el


function evt__formulario_emails__modificacion($datos)
{
	$cantidad_predeterminados = 0;
	foreach ($datos as $fila) {
		if ($fila['predeterminado'] == true) {
			$cantidad_predeterminados++;
		}
	}
	if (($cantidad_predeterminados > 1) ||
		(($cantidad_predeterminados == 0) && ($this->dep('formulario_emails')->get_cantidad_lineas() > 1))) {
		throw new toba_error('Debe predeterminarse un único email');
	} else {
		if (($cantidad_predeterminados == 0)  && ($this->dep('formulario_emails')->get_cantidad_lineas() == 1)) {
			$datos[0]['predeterminado'] = true;
		}
		$this->get_relacion()->tabla('docentes_emails')->procesar_filas($datos);	
	}
}

El problema es que al generar la excepción, los datos del formulario son vaciados y vuelven a cargar el valor original (vuelve a ejecutarse conf__formulario_emails). Hay forma de prevenir esto?

Hola Martin, paso a responderte los puntos:

  1. El ML tiene dos formas de trabajar con los eventos:
    a) JS donde los eventos se trabajan del lado cliente y luego se envian como un todo junto con los datos al servidor para ser procesados alli, esto lo recibis en el evento de modificacion del formulario. Esta es la forma actual que estas trabajando vos.

    b) Tipica de pagina web… donde cada evento dispara un pedido de pagina al servidor, es en este modo en el cual se dispara en el servidor el evento pedido_registro_nuevo.

No desesperes… todo tiene solucion o casi XD… lo que podrias hacer para mantener el esquema actual y realizar el control que necesitas es lo siguiente:

  • Extendes el formulario_ml y en el metodo ‘extender_objeto_js’ tendrias que colocar algo por el estilo:

     function extender_objeto_js()
     {
          echo "
                      var cantidad_filas = 0; 
                      var limite_filas = 5;                        //Este limite lo podes sacar de una variable
                     {$this->objeto_js}.crear_fila = function() {
                             var id_fila_nueva =  this.prototype.crear_fila.call();         //Llamo al padre
                             if (cantidad_filas > limite_filas) {
                                           notificacion.agregar('Superaste tu expectativa de vida', 'error');
                                           return false;
                             }
                             if (id_fila_nueva != 'undefined' && id_fila_nueva !== false) {
                                      cantidad_filas++;
                             }
                           return id_fila_nueva;
                      }
          ";
     }
   
  1. Teniendo algo como lo del punto anterior, lo que podrias hacer es antes de hacer el return id_fila_nueva; llamar a un metodo que te coloque los valores por defecto que necesitas, por ejemplo:

       {$this->objeto_js}.inicializar_valores_defecto = function (id_fila) {
             if (id_fila_nueva != 'undefined' && id_fila_nueva !== false) {
                  this.ef('nombre_ef1').ir_a_fila(id_fila).set_estado('estado_defecto1');   
                  this.ef('nombre_ef2').ir_a_fila(id_fila).set_estado('estado_defecto2');
                  //etc..
             }
       }

  1. Lo que te esta faltando en este caso es guardar los datos antes de lanzar la excepcion, esto podes hacerlo de dos maneras, con una variable de clase extra… o subiendo la llamada del procesar_filas… total hasta que no dispares el metodo de sincronizacion… dichos datos solo estan en el datos_tabla. Aca te presento la opcion de la variable extra por si te resulta mas comodo.

function evt__formulario_emails__modificacion($datos)
{
         $this->temporal_datos_recibidos = $datos;
	$cantidad_predeterminados = 0;
	foreach ($datos as $fila) {
		if ($fila['predeterminado'] == true) {
			$cantidad_predeterminados++;
		}
	}
	if (($cantidad_predeterminados > 1) ||
		(($cantidad_predeterminados == 0) && ($this->dep('formulario_emails')->get_cantidad_lineas() > 1))) {
		throw new toba_error('Debe predeterminarse un único email');
	} else {
		if (($cantidad_predeterminados == 0)  && ($this->dep('formulario_emails')->get_cantidad_lineas() == 1)) {
			$datos[0]['predeterminado'] = true;
		}
		$this->get_relacion()->tabla('docentes_emails')->procesar_filas($datos);	
	}
}

Luego en el metodo conf__formulario_emails:


function conf__formulario_emails($form)
{
    if (isset($this->temporal_datos_recibidos)) {
           $form->set_datos($this->temporal_datos_recibidos);
    }
}

Espero haberte sido de ayuda…
Saludos

Impecable!!! te cuento lo siguiente:
El punto 3) salió de una, utilicé la alternativa de subir replicar el proceso de las filas antes de lanzar la excepción, y si no hubo excepción para capturar.
Sobre el punto 1 y 2), salieron funcionando (cambié bastante el código y tuve que tomar en cuenta que podés eliminar líneas y luego deshacer esta eliminación)… igual sigo con un leve detalle, no sé como inicializar la variable limite_filas que pretendo tome el valor de la propieda Max.Filas de la tabla Emails del datos_relacion.


<?php
class formulario_emails extends toba_ei_formulario_ml
{
	function extender_objeto_js()
	{
		echo "
		 	cantidad_filas = {$this->objeto_js}.filas().length; 
		 	limite_filas   = 3;
		 	 	
       		        {$this->objeto_js}.crear_fila_orig = {$this->objeto_js}.crear_fila; 
			{$this->objeto_js}.crear_fila	   = function() {
				cantidad_filas++;
				if (cantidad_filas > limite_filas) {
					alert('No pueden ingresarse más de 3 emails', 'error');
					cantidad_filas--;
					return false;
				}
				id_fila = this.crear_fila_orig();
				this.ef('email').ir_a_fila(id_fila).set_estado('a@a.com'); //esto solo es una prueba... es codigo que utilizaré en otro ML
			}
			
			{$this->objeto_js}.eliminar_fila_orig = {$this->objeto_js}.eliminar_fila; 
			{$this->objeto_js}.eliminar_fila	  = function(fila) {
				cantidad_filas--;
				return this.eliminar_fila_orig(fila);
			}
			
			{$this->objeto_js}.deshacer_orig = {$this->objeto_js}.deshacer; 
			{$this->objeto_js}.deshacer	     = function() {
				cantidad_filas++;
				if (cantidad_filas > limite_filas) {
					alert('No pueden ingresarse más de 3 emails', 'error');
					cantidad_filas--;
					return false;
				}
				this.deshacer_orig();
			}
			
		";	
	}
}
?>

Además, te pido que lo “corrijas” ya que difiere mucho del tuyo, solo a los efectos de saber si estoy yendo por el camino equivocado, controlando poco, o tomando en cuenta alternativas que pudieran causar un problema en futuras versiones.
MIL GRACIAS!!!

Hola Martin,

En realidad venis vos mucho mejor que yo con el codigo XD… en la funcion de creacion de la fila hice cualquier desman. Asi que muy bien por entenderme a pesar de lo despiolado.

Con respecto al tema de inicializar la variable de acuerdo al tope maximo… lo podrias hacer asi:


<?php
class formulario_emails extends toba_ei_formulario_ml
{
	function extender_objeto_js()
	{
                  $limite_filas = $this->controlador()->get_relacion()->tabla('emails')->get_tope_max_filas();
                  if ($limite_filas == 0) {            //No existe tope y se pueden incorporar todas las filas que se deseen
                        $limite_filas = 10;             //Creo limite artificial
                  }

                  echo "
                                  cantidad_filas = {$this->objeto_js}.filas().length;
                                  limite_filas = $limite_filas;
                                  ....
                                  ....
                           ";
         }
}
?>

Ahi estoy asumiendo que en el CI tenes un metodo get_relacion que te devuelve una referencia a la dependencia del datos_relacion, si no es asi tranquilamente podes reemplazar eso por:

$this->controlador()->dep(‘nombre_dependencia_datos_relacion’)->tabla(‘emails’)->get_tope_max_filas();

Saludos

Bien!

En realidad venis vos mucho mejor que yo con el codigo XD... en la funcion de creacion de la fila hice cualquier desman. Asi que muy bien por entenderme a pesar de lo despiolado.
Es la punta del ovillo, después lo tiene que pelear cada uno... :) Son solo 2 respondiendo y muchos preguntando [b]ansiosos[/b]... es algo loable.

Al fin, quedó resuelto de esta forma, dejo el código final, funcionando para futuras referencias:


<?php
class formulario_emails extends toba_ei_formulario_ml
{
	function extender_objeto_js()
	{
		$limite_filas = $this->controlador()->get_relacion()->tabla('emails')->get_tope_max_filas();
		if ($limite_filas == 0) {
			$limite_filas = 3;    
		}
		echo "
		 	cantidad_filas = {$this->objeto_js}.filas().length;
		 	limite_filas   = $limite_filas;
		 	
			{$this->objeto_js}.crear_fila_orig = {$this->objeto_js}.crear_fila; 
			{$this->objeto_js}.crear_fila	   = function() {
				cantidad_filas++;
				if (cantidad_filas > limite_filas) {
					notificacion.agregar('No pueden ingresarse más de $limite_filas emails', 'error');
					notificacion.ventana_modal();
					notificacion.limpiar();
					cantidad_filas--;
					return false;
				}
				id_fila = this.crear_fila_orig();
			}
			
			{$this->objeto_js}.eliminar_fila_orig = {$this->objeto_js}.eliminar_fila; 
			{$this->objeto_js}.eliminar_fila	  = function(fila) {
				cantidad_filas--;
				return this.eliminar_fila_orig(fila);
			}
			
			{$this->objeto_js}.deshacer_orig = {$this->objeto_js}.deshacer; 
			{$this->objeto_js}.deshacer	     = function() {
				cantidad_filas++;
				if (cantidad_filas > limite_filas) {
					notificacion.agregar('No pueden ingresarse más de $limite_filas emails', 'error');
					notificacion.ventana_modal();
					notificacion.limpiar();
					cantidad_filas--;
					return false;
				}
				this.deshacer_orig();
			}
		";	
	}
}
?>

El código está basado en su estructura (hasta que me metí solito en estos detalles), en el ABM de Personas del proyecto Referencia.
Mil gracias!!!

Buenisimo Martin… una masa!!!,

solo un detalle extra, fijate que en el metodo crear_fila que extendiste no se esta devolviendo ningun valor… el original te devuelve el id_fila, agregandole eso te queda joya. Te lo comento porque puede surgir algun comportamiento medio extraño con el ML quizas ya que el resto de la API asume que retorna un valor la funcion esa.

Saludos
Richard

Ajustado… gracias… nuevamente!!