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.
NotemplatedoprocessoqueutilizaráAjax,énecessárioincluirabiblioteca!JavaScriptquepermitesuautilização.Paraisto,foidesenvolvidoumplugindoSmartyqueinsereosarquivosnecessários(garantindoquenãosejamincluídosmaisdeumavez).Parafazerinserçãodosarquivos!JavaScript,consulte:[wiki:WF_InicializaçãodoAjax]
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}
{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}
}}}
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}
{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}
}}}
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}
{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}
}}}
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}
{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 "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}
}}}