Grid

A principal ferramenta de apresentação de dados do Web Framework é a grade. A seguir será explicado o básico sobre o desenvolvimento da grade. Para uma visão mais aprofundada, a documentação da API deve ser consultada.

Declaração da grade

Uma grade é construída no contexto de um processo. Assim, a forma mais comum de declarar uma grade é por meio do método grid da classe Process. Em arquivos .ip ou .il (processos e relatórios respectivamente), o objeto do processo corrente pode ser acessado por this. Dessa forma, a declaração de uma grade poderia ser:

const grid = this.grid('nome da grade');

ou

this.ds = classes.getCachedDataSet(-2090000000);
const grid = this.grid('exemplo', this.ds);

Este método de Process pode ser usado para criar uma grade ou acessar pelo nome a instância já criada de uma grade.

O terceiro e o quarto parâmetros são opcionais, sendo respectivamente a chave da classe que terá definição de campos da grade e o objeto da grade mestre (fazendo uma relação masterDetail). Para mais detalhes de como declarar uma grade no processo, ver a documentação de Process.grid.

Objetos da classe Grid também possuem uma série de propriedades que podem ser editadas para modificar o comportamento da grade, como por exemplo, definir se ela pode editar, inserir, apagar, exportar ou duplicar registros. Para mais detalhes dessas propriedades, ver a documentação de Grid.

Registro de eventos

Após declarar a grade, normalmente são registrados os eventos, caso necessário. Eventos geralmente são disparados durante a construção da grade, como na definição de campos, por exemplo, e também antes e depois de ações na grade, como remoção, inclusão, confirmação de edição etc.

No exemplo a seguir, um evento pré-remoção é registrado:

grid.on('beforeDelete', function (evt) {
  if (evt.grid.ds.num('iNumber') < 10) {
    throw new Error('Registros com valores abaixo de 10 não podem ser removidos.');
  }
});

Para mais detalhes sobre cada evento, ver a documentação de eventos da grade.

Definição dos campos

Para acessar ou definir o campo de uma grade, utiliza-se o método field da classe Grid. Com o objeto field, é possível ler e editar o dado do campo do registro corrente, ou modificar suas propriedades.

Exemplo:

const fld = grid.field('non_negative');
const value = fld.getValue();
if (value < 0) {
    fld.setValue(0);
}

Por vezes, a grade declarada precisa ter seus campos definidos ou modificados no momento de sua construção, seja por não possuírem uma definição de classe de onde pegar a definição dos campos, seja por precisarem ter uma customização específica para o processo.

Para isso, usa-se o evento defineFields.

grid.on('defineFields', function (evt) {
  let fld = evt.grid.field('field_1');
  fld.label = 'Field 1';
  fld.help = 'Ajuda do campo 1';
  fld.on('lookupDisplay', function (evt) {
    evt.displayValue = DBKey.from(evt.key).str('iName');
  });

  fld = evt.grid.field('field_2');
  fld.label = 'Field 2';
  fld.readonly = true;

  fld = evt.grid.field('field_3');
  fld.visible = false;
});

Como é possível notar pelo exemplo acima, os campos podem ter propriedades modificadas e eventos registrados. Para mais detalhes, ver a documentação de Field.

Registros

Algumas propriedades da grade que permitem lidar com os registros:

  • maxRecordCount: define o número máximo de registros a serem exibidos por página no modo tabela.
  • maxSelectedRecords: define o número máximo de registros que podem ser selecionados.
  • selectedRecords: guarda a lista de bookmarks dos registros selecionados em um array.
  • unselectableRecords: define por meio de um array de bookmarks quais os registros não podem ser selecionados.

Também é possível percorrer todos os registros e acessar os valores de seus campos por meio do dataset da grade, acessível pela propriedade ds. Em alguns casos, é recomendado que um clone desse dataset seja feito, para evitar modificar apresentação dos dados para o usuário. Por exemplo, quando for necessário percorrer os registros desse dataset, filtrá-lo ou modificar seus índices.

Para criar o clone do dataset, faça:

const clone = grid.ds.newSharedDataSet();

O método newSharedDataSet também admite um parâmetro com opções, como por exemplo ds.newSharedDataSet({ sharedDelta: true }) para que o dataset tenha o delta compartilhado. Para mais informações, acesse a documentação da API.

Botões

Uma grade pode conter botões que desempenham ações a serem definidas pelo desenvolvedor. Para declarar um botão, basta utilizar o método button da classe Grid. Esse método cria um botão ou acessa pelo nome a instância de um botão já criado.

Exemplo:

grid.button('Tornar maiúsculas', function (bt){
   var grid = bt.parent
   var ds = grid.ds
   var selectedRecords = grid.selectedRecords
   for (var i = 0; i < selectedRecords.length; ++i){
     ds.bookmark = selectedRecords[i];
     ds.setField('NOME', ds.str('NOME').toUpperCase());
   }
});

O segundo parâmetro não precisa ser necessariamente uma função. Pode também ser o nome de uma atividade ou interação. Existem mais três parâmetros que definem, respectivamente, a ordem do botão, a chave do processo (para os casos em que o botão abre uma interação ou atividade em um processo diferente do atual) e se a interação ou atividade deverá ser aberta em nova aba.

Os botões visíveis da grade podem ser controlados pela propriedade visibleButtons, que é um array de objetos da classe Button ou de strings com os nomes dos botões.

Para mais informações do botão, acesse Grid.button e Button.

Botão “Duplicar registro” na grade

Devido a necessidade cada vez mais constante de se criar registros com base em outros, foi criado o botão “Duplicar registro” para todas as grades.

O comportamento

Por padrão o botão “Duplicar registro” irá duplicar todos os campos com exceção da grade e dos campo que possuam os nomes IKEY, CHAVE, IVERSION e VERSAO. Os campos de nome ICODE, CODIGO, INAME e TITULO serão duplicados por padrão com a adição do sufixo “+”.

Este comportamento pode ser alterado definindo a propriedade duplicateMode do campo. Esta propriedade pode receber os seguintes valores:

  • DuplicateMode.NONE: o valor do campo não será duplicado.
  • DuplicateMode.COPY: o valor do campo será duplicado integralmente, caso este campo seja uma grade os dados dela serão duplicados seguindo o comportamento padrão do botão.
  • DuplicateMode.COPY_ADDING_SUFFIX: o valor do campo será duplicado com a adição do sufixo “+”.

Alterando o comportamento

Suponhamos que queremos que uma grade detalhe tenha seus dados duplicados para um novo registro e que os items do seu campo “detailField” não recebam sufixo. Podemos fazer como no código abaixo:

Exemplo:

const DuplicateMode = require('@nginstack/web-framework/lib/classdef/DuplicateMode');
const CLASS_KEY = 12345;

const grid = this.grid('masterGrid', classes.getCachedDataSet(CLASS_KEY), CLASS_KEY);
grid.on('defineFields', function (evt) {
  const field = evt.grid.field('detailGrid');
  field.duplicateMode = DuplicateMode.COPY;
  field.grid.on('defineFields', function (evt) {
    evt.grid.field('detailField').duplicateMode = DuplicateMode.COPY;
  });
});

grid.write();

Alterando o comportamento via x-class

É possível informar que uma determinada classe não pode ter seus dados duplicados por padrão ara isso basta adicionar um x-class na classe desejada e definir a propriedade canDuplicate.

Exemplo: this.canDuplicate = false;

Os eventos

Há dois eventos que são executados a cada clique no botão “Duplicar registro” são eles:

  • beforeDuplicate: Executado antes de iniciar o processo de duplicação do registro;
  • afterDuplicate: Executado ao terminar o processo de duplicação do registro;
const DuplicateMode = require('@nginstack/web-framework/lib/classdef/DuplicateMode');
const CLASS_KEY = 12345;

const grid = this.grid('masterGrid', classes.getCachedDataSet(CLASS_KEY), CLASS_KEY);
grid.on('defineFields', function (evt) {
  const field = evt.grid.field('detailGrid');
  field.duplicateMode = DuplicateMode.COPY;
  field.grid.on('defineFields', function (evt) {
    evt.grid.field('detailField').duplicateMode = DuplicateMode.COPY;
  });
});

grid.on('beforeDuplicate', function(evt) {
  evt.grid.process.alert('Duplicando registros');
});

grid.on('afterDuplicate', function(evt) {
  evt.grid.process.alert('Registros duplicados com sucesso');
});
grid.write();

Botão “Mostrar/Ocultar” chaves na grade

Ao clicar no botão “Mostrar/Ocultar chaves” o comportamento visual do campo definido pelo desenvolvedor será sobreposto, permitindo ficar visível mesmo que tenha sido ocultado em um determinado modo de visão da grade.

Caso haja o desejo de não mostrar as chaves de uma determinada grade, foi criada a propriedade Grid. prototype.enableToggleKeyButton, esta permite desabilitar o botão.

Exemplo:

const CLASS_KEY = 12345;

const grid = this.grid('masterGrid', classes.getCachedDataSet(CLASS_KEY), CLASS_KEY);
grid.enableToggleKeyButton = false;
grid.write();