terça-feira, 15 de março de 2011

XPages - Como validar campos

Bom, falaremos sobre como validar campos em XPages.

Há campos, como o TextField que, em suas propriedades, há uma aba Validation, onde podemos definir duas validações básicas: campo requerido e tamanho do valor inserido no campo.

Mas outros campos, como ComboBox, esta aba não está disponível.

Além de que essas validações são básicas demais e muitas vezes precisamos de validações mais avançadas. Então devemos ir na aba All Properties e procurar por "validators".
Nessa propriedade, podemos clicar no + e adicionar diversos tipos de validators.
Aqui serão apresentados os principais validator para um campo, sendo eles: xp:validateConstraint, xp:validateLength, xp:validateRequired (quando você marca campo requerido naquela aba validator, esse validator é criado aqui automaticamente) e o mais importante de todos, que pode substituir todos os outros, xp:validateExpression.

Primeiro falaramos de duas propriedades comum a todos esses validators: loaded e message. A propriedade loaded é simplesmente quando esse validator será considerado. Você pode inserir uma expressão em JavaScript ou simplesmente colocar true ou false. A propriedade message é muito importante, pois ela é a propriedade que define qual a mensagem que aparecerá no "Display Error" ou "Display Errors" para o usuário ver.

Agora vamos falar individualmente dos validators.

xp:validateConstraint

Aqui você usará Expressões Regulares (regex). Caso você saiba fazê-las, você pode simplesmente inserir na propriedade regex. Caso não, pode procurar na internet regex feitas para validar o que você quiser. Por exemplo: uma regex que valide se o email é valido. Um site que eu aconselho para procurar regex prontas é http://regexlib.com/
Nele há várias regex para validar várias coisas, porém é em inglês e tem poucas regex brasileiras (como por exemplo para validar CEP, visto que nosso CEP é diferente do Zip Code deles). Você pode usar esse site http://www.pagecolumn.com/tool/regtest.htm para testar as regex que você encontrar lá, testando o que é validado e o que não é.
O problema desse validator é que ele é um pouco limitado. Se a validação é muito avançada, você dificilmente conseguirá bons resultados com esse.

xp:validateLength

Tem a mesma função daquele validator da aba Validation. Simplesmente você coloca o tamanho mínimo e/ou máximo que a STRING inserida deve ter. Lembre-se, ele não validará o tamanho de um número.

xp:validateRequired

Simplesmente torna o campo requerido. Mesma função do encontrado na aba Validation.

xp:validateExpression

Com esse você pode fazer qualquer tipo de validação usando JavaScript. A propriedade clientScript é apenas usada quando você quer fazer alguma validação com Client-Side JavaScript. Mas no geral, usaremos expression para usar o Server-Side JavaScript.
Você deve clicar no diamante e clicar em compute value, então abrirá a seguinte janela:
Nessa janela você poderá usar códigos JavaScript para validar seu campo. Para pegar o valor do campo que você está validando, você deve usar:
getComponent("nomeDoCampo").getSubmittedValue()
Então você processa em cima dele. É usado o SubmittedValue porque no momento em que aquele campo está sendo validado, o valor dele está sendo submetido ao servidor. Mas no caso de você pegar o valor de um outro campo que não seja onde está sendo feito o validator, você deve usar apenas Value, da seguinte forma:
getComponent("nomeDoOutroCampo").getValue()
Lembrando que quando seu código retornar true, significa que foi validada a entrada, que não houve problemas. Quando seu código retornar false, houve algum erro e a mensagem de erro definida será emitida.
Veja exemplos:
Uma outra forma é você, na aba da esquerda dessa janela, selecionar Control Declaration Snippets. Lá estarão todos os campos de sua página. Dando um clique duplo em um dos campos, será inserido automaticamente uma variavel recebendo o getComponent do campo. Nas linhas abaixo, você pode usar essa variável e verá que os métodos em cima dessa variável serão completados.



Esses são os principais validators (pelo menos para mim). Em geral, você pode usar apenas o validateExpression para tudo.
Uma coisa importante de se fazer quando você criar um validator é colocar true na propriedade disableClientSideValidation.
Isso fará com que suas mensagens apareçam no Display Error ou no Display Errors, de acordo com qual você estiver usando.
Para quem não conhece esses dois componentes, eles são components para mostrar mensagens de erro para o cliente. Você pode inserir um Display Error do lado ou perto do campo que você quiser e nas propriedades dele selecionar para qual campo ele será relacionado. O Display Errors simplesmente mostrará uma lista de erros de todos os validators da página.

XPages - Trabalhando com DbColumn e DbLookup

Assim como no Notes, podemos usar @DbColumn e @DbLookup em XPages através de JavaScript. Há apenas algumas diferenças.


A sintaxe básica desses dois comandos em XPages é:

@DbLookup(dbName:string, viewName:string, key:string, colNumber:int) : any
@DbLookup(dbName:string, viewName:string, key:string, fieldName:string) : any
@DbLookup(dbName:string, viewName:string, key:string, colNumber:int, keywords:string) : any
@DbLookup(dbName:string, viewName:string, key:string, fieldName:string, keywords:string) : any
DbColumn(dbName:string, viewName:string, colNumber:int) : any

Bastante parecida com a sintaxe usada no próprio Notes.
Mas devemos ter muita atenção ao trabalhar com esses dois comandos, pois eles podem retornar: Array, String ou null. Diferente de comandos convencionais que usamos em JavaScript, esse comando pode retornar instancias diferentes de acordo com seu resultado. Caso encontre mais de um resultado, ele retorna uma instancia de Array com os resultados; caso encontre apenas um resultado, ele não retornará um Array com um elemento, mas sim o elemento; caso não encontre nada, ele retornará null. Então sempre devemos tratar os resultados de acordo com o que pode aparecer. Mas de tudo isso que falei acima, o @DbColumn tem apenas uma diferença, onde retornaria null, retorna "".

Eu sugiro usar o seguinte código ao usar esses 2 comandos:

var x = @DbLookup(@DbName(), "ViewQualquer", key, 1);
if(x instanceof Array){
    //Código para quando retornar um Array
}
else{
   if(x == null){
        //Código para quando não retornar resultados
    }
    else{
        //Código para quando retornar apenas um elemento
    }
}



var x = @DbColumn(@DbName(), "ViewQualquer", 1);
if(x instanceof Array){
    //Código para quando retornar um Array
}
else{
   if(x == ""){
        //Código para quando não retornar resultados
    }
    else{
        //Código para quando retornar apenas um elemento
    }
}

terça-feira, 1 de março de 2011

XPages - Como validar se o documento foi modificado por outro usuário

Os métodos que encontramos para validar isso costumam ser os mais complicados possíveis, geralmente dando 'lock' no documento, rodando agents, etc. Procurando como fazer isso, acabei tendo a idéia de desenvolver um simples validator que o fizesse.
Essa validação é algo muito importante, para um usuário não sobescrever o que o outro acabou de fazer e também para evitar conflitos em geral.
Bom, vamos lá.

Após já ter um NotesXspDocument definido em Data da XPage ou Custom Control, vá em eventos da página, entre no nome definido em Data por você (por padrão, document1) e então no evento "postOpenDocument". Apenas insira um evento com o seguinte código:


viewScope.acessado = @Now();


Agora crie um validator (validateExpression) em apenas UM dos campos da página. Em expression insira o seguinte código:

if(!document1.isNewNote()){
    var modificado:Date = document1.getDocument().getLastModified().toJavaDate();
    var acessado:Date = viewScope.acessado;
    return modificado.getTime() < acessado.getTime();
}
else{
    return true;
}

Agora vá em message do validator e selecione Compute value. Apenas insira o seguinte código (modificando a mensagem, caso queira):

var modificado:Date = document1.getDocument().getLastModified().toJavaDate();
return "O documentou foi modificado por outro usuário em " + modificado.toString() + ", atualize a página para evitar conflitos!";


Pronto! Agora, caso um usuário abra a página e enquanto ele edita um outro salvou, o validator irá validar isso e avisá-lo. Lembrando, é claro, que deve-se ter um Error Message vinculado ao campo ou um Error Messages na página.