wiki:WF/UtilizacaodeAjaxemprocessos

Version 9 (modified by viani, 16 years ago) (diff)

--

Utilização de Ajax em Processos

TOC(heading=Workflow,depth=1,WF/Changelog,WF/Documentacao,WF/Instalacao,WF/Links,WF/Propostas)?

A utilização de Ajax em processos de Workflow requer a utilização de alguns padrões.

O código que será executado pelo Ajax deverá estar contido no método de uma classe (ou seja, não será possível executar funções "soltas").

O arquivo que contém a classe deverá estar localizado na área "code" (que é o mesmo diretório do arquivo shared.php) do processo. O nome deverá seguir o formato: class.ajax.nome_classe.inc.php, por exemplo, supondo que irei chamar, por Ajax, a classe validacao, então o nome do arquivo que contém a classe deverá ser: class.ajax.validacao.inc.php

Quando a classe for instanciada, seu construtor será chamado sem parâmetros.

No template do processo que utilizará Ajax,é necessário incluir a bibliotecaJavaScript que permite sua utilização.Para isto, foi desenvolvido um plugin do Smarty que insere os arquivos necessários( garantindo que não sejam incluídos maisdeumavez).Para fazer inserção dos arquivosJavaScript, consulte: Inicialização do Ajax

A especificação de qual classe e método será chamado, é feita através do método addVirtualRequest da classe NanoController (JavaScript). Este método aceita três parâmetros, são eles (em ordem):

um identificador da chamada Ajax.

um objeto JavaScript com os atributos:

action: contendo o nome da classe que será chamada

mode: o nome do método da classe que será chamado

um ojeto JavaScript contendo eventuais parâmetros para a chamada (este parâmetro é opcional)

No caso dos dois últimos parâmetros, é possível fazer a definição dos objetos in loco.

Exemplo de utilização

Classe PHP no arquivo class.ajax.minhas_strings.inc.php

class minhas_strings()
{

	var $nome;

	function minhas_strings()
	{
		$this->nome = "Mundo";

	}

	function saudacao()
	{

		return "Olá " . $this->nome;

	}
	

	function adeus()
	{
		return "Adeus " . $this->nome . " cruel";

	}

	

	function saudacaoEspecial($params)
	{

		return $params['cumprimento'] . " " . $this->nome;

	}

}

No meu arquivo de templates, eu posso fazer uma chamada para um método da classe Ajax da seguinte forma:

{wf_ajax_init}

<script language="javascript">

{literal}

var nc = new NanoController();

nc.setWfUrl();

nc.setSuccessHandler(exibirResultado);

nc.addVirtualRequest('chamada_1',
	{

		action : 'minhas_strings',
		mode   : 'saudacao'

	});

nc.sendRequest();



function exibirResultado(dados)
{

	/* irá exibir um alerta com a string "Olá Mundo" */

	alert(dados['chamada_1']['data']);

}

{/literal}

</script>

A tag Smarty {{literal}} indica que o smarty não irá tentar interpetrar as chaves como sendo seus delimitadores.

Com a biblioteca de Ajax utilizada, que é a NanoAjax, é possível fazer várias chamadas a métodos em uma única chamada Ajax. Sendo assim, o exemplo abaixo chama dois métodos da classe "minhas_strings" (as chamadas não precisam ficar restritas a apenas uma classe).

{wf_ajax_init}

<script language="javascript">

{literal}

var nc = new NanoController();

nc.setWfUrl();

nc.setSuccessHandler(exibirResultado);

nc.addVirtualRequest('chamada_1',
	{

		action : 'minhas_strings',
		mode   : 'saudacao'

	});

nc.addVirtualRequest('chamada_2',
	{

		action : 'minhas_strings',
		mode   : 'adeus'

	});

nc.sendRequest();


function exibirResultado(dados)

{

	/* irá exibir um alerta com a string "Olá Mundo" */

	alert(dados['chamada_1']['data']);

	/* irá exibir um alerta com a string "Adeus Mundo cruel" */

	alert(dados['chamada_2']['data']);

}

{/literal}

</script>

Também é possível chamar um método passando um ou mais parâmetros. Um exemplo que passa um parâmetro pode ser visto abaixo:

{wf_ajax_init}

<script language="javascript">

{literal}

var nc = new NanoController();

nc.setWfUrl();

nc.setSuccessHandler(exibirResultado);

nc.addVirtualRequest('chamada_especial',
	{

		action : 'minhas_strings',

		mode   : 'saudacaoEspecial'

	},

	{
		cumprimento: 'Oi'

	});

nc.sendRequest();

function exibirResultado(dados)
{

	/* irá exibir um alerta com a string "Oi Mundo" */

	alert(dados['chamada_especial']['data']);

}

{/literal}

</script>

Uma outra coisa que pode ser feita, é a utilização de um handler próprio no caso de um erro na chamada Ajax. Exemplo:

{wf_ajax_init}

<script language="javascript">

{literal}

var nc = new NanoController();

nc.setWfUrl();

nc.setSuccessHandler(exibirResultado);

nc.setExceptionHandler(tratarErro);

nc.addVirtualRequest('vai_dar_erro',
	{

		action : 'minhas_strings',
		mode   : 'metodo_inexistente'

	},

	{

		cumprimento: 'Oi'

	});

nc.sendRequest();

/* esta função não será chamada pois ocorrerá um erro devido à não existência do método [[BR]]
"metodo_inexistente" da classe "minhas_strings" */

function exibirResultado(dados)
{
	alert(dados['vai_dar_erro']['data']);

}


/* função que trata erros na chamada Ajax */

function tratarErro(dados)
{

	/* aqui o meu erro será tratado */
	alert("Houve um erro neste procedimento.\nPor favor, contacte o administrador");

}
{/literal}
</script>

Agora um outro exemplo, que faz acesso a banco de dados:

{wf_ajax_init}

<script language="javascript">

{literal}

function alterarValor(externoID, p_usuario, p_data, p_valor)
{
	var resultAlterarValor = function(data)
	{
		if (data['valor']['data']['erro'])
		{
			alert(data['valor']['data']['erro']);
			/* trata o erro */
		}
		else
		{
			var externo = $(externoID);
			externo.innerHTML = data['valor']['data']['valor'];
		}
	}

	var nc = new NanoController();
	nc.setWfUrl();
	nc.setSuccessHandler(resultAlterarValor);
	nc.addVirtualRequest('valor',
		{
			action : 'definir_valores',
			mode   : 'valor'
		},
		{
			usuario: p_usuario,
			data_hora: p_data,
			valor: p_valor
		});
	nc.sendRequest();
	$(externoID).innerHTML = '<font color="grey">atualizando..</font>';
}

A classe php invocada por este código JavaScript seria: (class.ajax.definir_valores.php)

<?php
class definir_valores
{
	var $db;
	var $schema;

	function definir_valores()
	{
		$this->db = wf_create_object('wf_db');
		$this->db->connect();
		$this->schema = "ligacoes_telefonicas";
	}

	function valor($params)
	{
		$output = array();

		$valor = str_replace(",", ".", str_replace(".", "", $params['valor']));
		$usuario = (int) $params['usuario'];
		$data_hora = $params['data_hora'];

		if (!is_numeric($valor))
			$output['erro'] = "\"" . $params['valor'] . "\" é um valor inválido";
		else
		{
			$valor = (double) $valor;
			$sqlStatement = "UPDATE {$this->schema}.ligacao_telefonica SET valor = ? 
						WHERE (data_hora = ?) AND (usuario = ?)";
			$resultado = $this->db->query($sqlStatement, array($valor, $data_hora, $usuario));
			$this->db->disconnect();
			if ($resultado)
				$output['valor'] = $params['valor'];
			else
				$output['erro'] = "Ocorreu um erro ao atualizar o valor desta ligação.";
		}
		return $output;
	}
}
?>