# Formulário - customizar com HTML, C#, CSS e Javascript

O agilityflow também pode ser customizado através da Linguagem Html, CSS, Javascript e C# (csharp).

O html do agilityflow é baseado no Razor do framework .Net, isso é, você pode além de customizar com HTML, utilizar código C# (razor) para dar mais flexibilidade e poder ao seu componente Html.

#### O que e onde customizar?

Acesse a parte de Desenvolvimento do Formulário que você deseja customizar, para isso, entre na área de customização de um formulário e clique na opção Visual Code Editor, como na imagem abaixo:

![](https://wiki.agilityflow.io/uploads/images/gallery/2021-03-Mar/scaled-840-0/image-1616509257635.png)

No Visual Code editor, no menu esquerdo, serão apresentados as seguintes opções:

- **Style (CSS):**  opção para customizar o CSS de todo o formulário.
- **Javascript:**  opção para customizar o Javascript de todo o formulário.
- **Componente CsHtml:** opção para criar novos componentes em HTML

![](https://wiki.agilityflow.io/uploads/images/gallery/2021-03-Mar/scaled-840-0/image-1616592273241.png)

### Style (CSS)

Nessa área, você pode criar customizações via linguagem CSS para todo o formulário, o seu uso é livre.

<p class="callout warning">Levar em consideração o tratamento em CSS para a responsividade da plataforma em outros device, Mobile, Computador Desktop, Tablet, etc.</p>

### Javascript: 

Nessa área, você pode criar customizações via linguagem Javascript para todo o formulário, o seu uso é livre.

Você pode utilizar jquery e outras bibliotecas já declaradas no código-fonte por padrão (veja lista mais abaixo).

<span style="text-decoration: underline;">Exemplo de utilização:</span>

No código javascript abaixo, a regra impede que um formulário de projetos que esteja com o status "inativo", seja salvo:

```JavaScript
var projeto = {
    init: function () {
        projeto._setEvents(); //registrar os eventos que são inerentes a esse bloco de código
    },
    _setEvents: function () {

      	//ao fazer o submit do formulário executa a função de validação de status
        $('#formulario').on('submit', function (e) {
            projeto.validarStatus();
        })

    },
    validarStatus: function () {

      	//recupera através de jquery o valor do campo "Status do Projeto"
        var status_projeto = $("#status_projeto").val();
      
      	//verifica se o tipo de envio que o formulário está requisitando no submit 
        //é do tipo "SALVAR" e se o status é "inativo"
        //caso seja, inválida o submit e apresenta uma aviso para o usuário
        if (Form.getFormActionOnSubmit() == ACTION_SALVAR && status_projeto == "inativo") {

            //inválida o submit e apresenta uma aviso para o usuário
            Form.invalidateForm({
                msg: 'Um projeto inativo não pode ser salvo.'
            });

        }
 
    }
}
projeto.init(); //iniciando e configurando
```

Abaixo estão listadas algumas funções nativas do agility**Flow** para javascript:

#### **Como utilizar funções Javascript dentro de um CSHTML**

<p class="callout info">Caso você utilize Javascript dentro de um componente HTML (CSHTML), é necessário que o código esteja dentro da função **DOM.ready (como no exemplo abaixo)** para garantir que o seu código só execute após todo o carregamento de todos as funções Javascript</p>

<p class="callout danger">Recomendamos que dentro do arquivo CSHTML só tenha a "chamadas" para as funções que estejam programadas dentro do arquivo específico para o código Javascript.</p>

```JavaScript
<script>
    DOM.ready(function () {
  
  		//seu código javascript aqui
  
    });
</script>
```

#### **Funções Javascript Nativas**

##### Recuperar data do servidor:

```JavaScript
GetDateNow()
```

<p class="callout warning">A data e hora são obtidas dos servidores do Agilityflow, para assim garantir a confiabilidade da data e hora</p>

<p class="callout info">**Atenção:** Lembre-se que no Javascript o retorno do método ".getMonth()" de um objeto **Date**, não refere-se ao mês e sim a Índice daquele mês no array de meses, sendo assim, o retorno desse método sempre será entre os valores **0 até 11** e não de 1 a 12</p>

Exemplo de como configurar o valor inicial de um campo com a data atual.

Para esse exemplo, encare que o ID do campo que estamos preenchendo com a data atual é "data".

```JavaScript
var exemplo1 = {
    init: function () {
        exemplo1.setToday();
    },
    //coloca a data atual no campo de data
    setToday: function () {

        if ($('#data').val() != "") return;

        //data do servidor para garantir que seja uma data válida
        var date = GetDateNow();

        var day = date.getDate().toString().padLeft(2, '0');
        var year = date.getFullYear();
        var monthIndex = date.getMonth()
        monthIndex++;
        if (monthIndex > 12)
            monthIndex = 1;


        $('#data').val(day.toString().padLeft(2, '0') + '/' + monthIndex.toString().padLeft(2, '0') + '/' + year);

    }
}
exemplo1.init();
```

##### Comparar uma data com a data atual (Hoje):

<p class="callout info">Essa comparação desconsidera a HORA</p>

A função é: **formContext.datetime.validation.compareToday(comparador, data)**

Os possíveis comparadores são:

<table border="1" id="bkmrk-greater-greater-or-e" style="border-collapse: collapse; width: 100%; height: 186px;"><tbody><tr style="height: 31px;"><td style="width: 25%; height: 31px;">**Tipo**</td><td style="width: 32.9012%; height: 31px;"><div><div>Opção 1 (qualquer uma das opções)</div></div></td><td style="width: 42.0988%; height: 31px;"><div><div>Opção 2 (qualquer uma das opções)</div></div></td></tr><tr style="height: 31px;"><td style="width: 25%; height: 31px;"><div><div>**maior que**</div></div></td><td style="width: 32.9012%; height: 31px;"><div><div>&gt;</div></div></td><td style="width: 42.0988%; height: 31px;"><div><div>greater </div></div></td></tr><tr style="height: 31px;"><td style="width: 25%; height: 31px;"><div><div>**maior ou igual** </div></div></td><td style="width: 32.9012%; height: 31px;"><div><div>&gt;=</div></div></td><td style="width: 42.0988%; height: 31px;"><div><div>greater-or-equal</div></div></td></tr><tr style="height: 31px;"><td style="width: 25%; height: 31px;"><div><div>**menor**</div></div></td><td style="width: 32.9012%; height: 31px;"><div><div>&lt;</div></div></td><td style="width: 42.0988%; height: 31px;"><div><div>less</div></div></td></tr><tr style="height: 31px;"><td style="width: 25%; height: 31px;"><div><div>**menor ou igual**</div></div></td><td style="width: 32.9012%; height: 31px;"><div><div>&lt;=</div></div></td><td style="width: 42.0988%; height: 31px;"><div><div>less-or-equal</div></div></td></tr><tr style="height: 31px;"><td style="width: 25%; height: 31px;"><div><div>**igual**</div></div></td><td style="width: 32.9012%; height: 31px;"><div><div>==</div></div></td><td style="width: 42.0988%; height: 31px;"><div><div>equal</div></div></td></tr></tbody></table>

```JavaScript
var greater = formContext.datetime.validation.compareToday('greater', '31/12/2000');
console.log('greater',greater);

var greater_or_equal = formContext.datetime.validation.compareToday('greater-or-equal', '31/12/2000');
console.log('greater-or-equal', greater_or_equal);

var less = formContext.datetime.validation.compareToday('less', '31/12/2000');
console.log('less',less);

var less_or_equal = formContext.datetime.validation.compareToday('less-or-equal', '31/12/2000');
console.log('less-or-equal', less_or_equal);

var equal = formContext.datetime.validation.compareToday('equal', '31/12/2000');
console.log('equal', equal);

```

##### Comparação entre datas. Comparar 2 datas:

<p class="callout info">Essa comparação desconsidera a HORA</p>

A função é: **formContext.datetime.validation.compare(data1, comparador, data2)**

Os possíveis comparadores são:

<table border="1" id="bkmrk-tipo-op%E3%A7%E3%A3o-1-%28qual" style="border-collapse: collapse; width: 100%; height: 186px;"><tbody><tr style="height: 31px;"><td style="width: 25%; height: 31px;">**Tipo**</td><td style="width: 32.9012%; height: 31px;"><div><div>Opção 1 (qualquer uma das opções)</div></div></td><td style="width: 42.0988%; height: 31px;"><div><div>Opção 2 (qualquer uma das opções)</div></div></td></tr><tr style="height: 31px;"><td style="width: 25%; height: 31px;"><div><div>**maior que**</div></div></td><td style="width: 32.9012%; height: 31px;"><div><div>&gt;</div></div></td><td style="width: 42.0988%; height: 31px;"><div><div>greater </div></div></td></tr><tr style="height: 31px;"><td style="width: 25%; height: 31px;"><div><div>**maior ou igual** </div></div></td><td style="width: 32.9012%; height: 31px;"><div><div>&gt;=</div></div></td><td style="width: 42.0988%; height: 31px;"><div><div>greater-or-equal</div></div></td></tr><tr style="height: 31px;"><td style="width: 25%; height: 31px;"><div><div>**menor**</div></div></td><td style="width: 32.9012%; height: 31px;"><div><div>&lt;</div></div></td><td style="width: 42.0988%; height: 31px;"><div><div>less</div></div></td></tr><tr style="height: 31px;"><td style="width: 25%; height: 31px;"><div><div>**menor ou igual**</div></div></td><td style="width: 32.9012%; height: 31px;"><div><div>&lt;=</div></div></td><td style="width: 42.0988%; height: 31px;"><div><div>less-or-equal</div></div></td></tr><tr style="height: 31px;"><td style="width: 25%; height: 31px;"><div><div>**igual**</div></div></td><td style="width: 32.9012%; height: 31px;"><div><div>==</div></div></td><td style="width: 42.0988%; height: 31px;"><div><div>equal</div></div></td></tr></tbody></table>

```JavaScript
var greater = formContext.datetime.validation.compare('31/01/2001','greater', '31/12/2000');
console.log('greater',greater);

var greater_or_equal = formContext.datetime.validation.compare('31/01/2001','greater-or-equal', '31/12/2000');
console.log('greater-or-equal', greater_or_equal);

var less = formContext.datetime.validation.compare('31/01/2001','less', '31/12/2000');
console.log('less',less);

var less_or_equal = formContext.datetime.validation.compare('31/01/2001','less-or-equal', '31/12/2000');
console.log('less-or-equal', less_or_equal);

var equal = formContext.datetime.validation.compare('31/01/2001','equal', '31/12/2000');
console.log('equal', equal);


```

##### Recuperar o ID do usuário logado: 

```JavaScript
GetUserId()
```

##### Recuperar o nome do usuário logado: 

```JavaScript
var nome = pageNavigation.getUserName();
var nomeCompleto = pageNavigation.getUserNameCompleto()
```


##### Recuperar os Perfis do usuário logado: 

```JavaScript
GetUserProfileId() //retorna um array com os Ids dos perfis ['xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx','xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx']
```

##### Função para identificar se o usuário logado tem um determinado perfil: 

```JavaScript
UserHasProfileId('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx') //retorna true ou false
```

<span style="font-size: 1.4em; font-weight: 500; color: #555555;">Expandir e Recolher um determinado painel de campos</span>

```JavaScript
var panelId = 'f175132d-5e85-778f-1354-cb2d339e6146';

//para alternar entre expandido e recolhido
formContext.panel.collapse.toggle(panelId)

//para recolher o painel
formContext.panel.collapse.hide(panelId)

//para expandir o painel
formContext.panel.collapse.show(panelId)

//para testar se o painel está recolhido ou não
formContext.panel.collapse.isCollapsed(panelId) 
```

##### Recuperar os valores das "Variáveis de Ambiente"

Para saber mais sobre variáveis de ambiente entre em [Variáveis de ambiente](https://wiki.agilityflow.io/link/88#bkmrk-page-title)

```JavaScript
var valor = GetEnvironmentVariable("nomeDaVariavel")
```

Recuperar a Descrição (texto), no caso de variáveis do Tipo "Query com Id + Descrição":

```JavaScript
var text = GetEnvironmentVariable_Text("nomeDaVariavel")
```

##### Recuperar o VALOR preenchido de um campo no Formulário

```JavaScript
var value = Form.getValueField("idDoCampo");
```

<span style="font-size: 1.4em; font-weight: 500; color: #555555;">Recuperar o VALOR preenchido de um campo no Formulário PAI (formulário que abriu o formulário atual)</span>

```JavaScript
var value = Form.getValueField_parentIFrame("idDoCampo");
```

##### Recuperar o TEXTO preenchido de um campo no Formulário (Para os campos: <span style="text-decoration: underline;">Lista de Seleção</span> e <span style="text-decoration: underline;">Pesquisa com Auto Completar</span>)

```JavaScript
var value = Form.getTextField("idDoCampo");
```

##### Recuperar o TEXTO preenchido de um campo no Formulário PAI (formulário que abriu o formulário atual) (Para os campos: <span style="text-decoration: underline;">Lista de Seleção</span> e <span style="text-decoration: underline;">Pesquisa com Auto Completar</span>)

```JavaScript
var value = Form.getTextField_parentIFrame("idDoCampo");
```

##### Preencher um valor em um campo do Formulário

Parâmetros opcionais da função javascript

<table border="1" id="bkmrk-par%E3%A2metro%E2%A0opcional" style="border-collapse: collapse; width: 100%; height: 116px;"><tbody><tr style="height: 31px;"><td style="width: 25%; height: 31px;">**Parâmetro opcional**</td><td style="width: 15.0926%; height: 31px;">**Valor padrão**</td><td style="width: 20.7716%;">**Opções de valores**</td><td style="width: 39.1358%; height: 31px;">**Descrição**</td></tr><tr style="height: 85px;"><td style="width: 25%; height: 85px;">setOnlyIfFieldValueIsEmpty</td><td style="width: 15.0926%; height: 85px;">false</td><td style="width: 20.7716%;">true ou false</td><td style="width: 39.1358%; height: 85px;">Caso seja "**true**" a função só preencherá o valor do campo se o campo ainda **NÃO** estiver preenchido.

Caso seja "**false**" a função preenche ou substitui o valor do campode qualquer maneira.

</td></tr></tbody></table>

```JavaScript
//EXEMPLO 1: preenchendo o valor
Form.setValueField("idDoCampo", "value");



//EXEMPLO 2: preenchendo o valor e enviando os parametros opcionais para a função:
var options = { setOnlyIfFieldValueIsEmpty: true  }
Form.setValueField("idDoCampo", "value", options);

```

##### Preencher um valor em um campo do Formulário PAI (formulário que abriu o formulário atual)

Parâmetros opcionais da função javascript

<table border="1" id="bkmrk-par%E3%A2metro%E2%A0opcional-0" style="border-collapse: collapse; width: 100%; height: 116px;"><tbody><tr style="height: 31px;"><td style="width: 25%; height: 31px;">**Parâmetro opcional**</td><td style="width: 15.0926%; height: 31px;">**Valor padrão**</td><td style="width: 20.7716%;">**Opções de valores**</td><td style="width: 39.1358%; height: 31px;">**Descrição**</td></tr><tr style="height: 85px;"><td style="width: 25%; height: 85px;">setOnlyIfFieldValueIsEmpty</td><td style="width: 15.0926%; height: 85px;">false</td><td style="width: 20.7716%;">true ou false</td><td style="width: 39.1358%; height: 85px;">Caso seja "**true**" a função só preencherá o valor do campo se o campo ainda **NÃO** estiver preenchido.

Caso seja "**false**" a função preenche ou substitui o valor do campode qualquer maneira.

</td></tr></tbody></table>

```JavaScript
//EXEMPLO 1: preenchendo o valor
Form.setValueField_parentIFrame("idDoCampo", "value");


//EXEMPLO 2: preenchendo o valor e enviando os parametros opcionais para a função:
var options = { setOnlyIfFieldValueIsEmpty: true }
Form.setValueField_parentIFrame("idDoCampo", "value", options);


```

##### Customizar evento de submit do formulário (Antes do post):

```JavaScript
$('#formulario').on('submit', function (e) { 
		/*
          função js para executar antes do 
          post e após a validação padrão do agilityflow
          
        */  
})

```

No [exemplo de javascript](http://wiki.agilityflow.io/link/78#bkmrk-exemplo-de-customiza), nas linhas de 5 a 12 usamos o código para interceptar o submit e validar o status do projeto.

##### Forçar o Salvar do formulário:

[Clique aqui para visualizar detalhes de Como forçar o salvamento de um Form](https://wiki.agilityflow.io/books/manual-de-customiza%C3%A7%C3%A3o/page/for%C3%A7ar-o-salvamento-de-um-form "Forçar o salvamento de um Form")

##### Escutar o evento de retorno de um submit no form:

[Clique aqui para visualizar detalhes de Como escutar o evento de retorno de um submit no form](https://wiki.agilityflow.io/books/manual-de-customiza%C3%A7%C3%A3o/page/evento-javascript-ap%C3%B3s-o-subsmit-post-do-formulario-%28onafterpostevent%29 "Evento javascript após o subsmit post do formulario (onAfterPostEvent)")

##### Invalidar o post/submit do formulário:

Para evitar que o formulário seja postado, você pode utilizar a seguinte função no evento de submit

```JavaScript
$('#formulario').on('submit', function (e) {
  
    //invalidar submit
    Form.invalidateForm({
      msg: 'Mensagem para o usuário.'
    });
  
})
```

No [exemplo de javascript](http://wiki.agilityflow.io/link/78#bkmrk-exemplo-de-customiza), nas linhas de 23 a 26 usamos o código para bloquear o submit caso o status do projeto seja inválido.

##### Verificar qual foi o botão clicado pelo usuário no submit do formulário. Se foi o salvar, salvar rascunho, descartar, deletar, aprovar, retornar, reprovar e assim por diante...

Os tipos de ações que o usuário pode realizar em um formulário são:

- Salvar (**ACTION\_SALVAR**)
- Salvar rascunho (**ACTION\_SALVAR\_RASCUNHO**)
- Descartar rascunho (**ACTION\_DESCARTAR\_RASCUNHO**)
- Aprovar (**ACTION\_APROVAR**)
- Reprovar (**ACTION\_REPROVAR**)
- Retornar (**ACTION\_RETORNAR**)
- Deletar (**ACTION\_DELETAR**)
- Salvar formulário filho (**ACTION\_SALVAR\_FORMULARIO\_FILHO**)
- Deletar formulário filho (**ACTION\_DELETAR\_FORMULARIO\_FILHO**)
- Descartar alterações formulário filho (**ACTION\_DESCARTAR\_ALTERACOES\_FORMULARIO\_FILHO**)
- Solicitar troca de aprovador na etapa (**ACTION\_SOLICITAR\_TROCA\_APROVADOR\_ETAPA\_DINAMICA**)
- Salvar o novo aprovador definido para a etapa (**ACTION\_SALVAR\_DEFINICAO\_APROVADOR\_ETAPA\_DINAMICA**)

Abaixo o exemplo para recuperar a ação:

```JavaScript
$('#formulario').on('submit', function (e) {
  
  		var tipoAcao = Form.getFormActionOnSubmit();
  		if(tipoAcao == ACTION_SALVAR){
          
            //ação para "Salvar"
          
        }else if(tipoAcao == ACTION_SALVAR_RASCUNHO){
          
            //ação para "Salvar rascunho"
          
        }else if(tipoAcao == ACTION_DESCARTAR_RASCUNHO){
          
            //ação para "Descartar rascunho"
          
        }else if(tipoAcao == ACTION_APROVAR){
          
            //ação para "Aprovar"
          
        }else if(tipoAcao == ACTION_REPROVAR){
          
            //ação para "Reprovar"
          
        }else if(tipoAcao == ACTION_RETORNAR){
          
            //ação para "Retornar"
          
        }else if(tipoAcao == ACTION_DELETAR){
          
            //ação para "Deletar"
          
        }else if(tipoAcao == ACTION_SALVAR_FORMULARIO_FILHO){
          
            //ação para "Salvar formulário filho"
          
        }else if(tipoAcao == ACTION_DELETAR_FORMULARIO_FILHO){
          
            //ação para "Deletar formulário filho"
          
        }else if(tipoAcao == ACTION_DESCARTAR_ALTERACOES_FORMULARIO_FILHO){
          
            //ação para "Descartar alterações formulário filho"
          
        }else if(tipoAcao == ACTION_SOLICITAR_TROCA_APROVADOR_ETAPA_DINAMICA){
          
            //ação para "Solicitar troca aprovador etapa dinâmica"
          
        }else if(tipoAcao == ACTION_SALVAR_DEFINICAO_APROVADOR_ETAPA_DINAMICA){
          
            //ação para "Salvar definicão de  aprovador etapa dinâmica"
          
        }
  
})
```

No [exemplo de javascript](http://wiki.agilityflow.io/link/78#bkmrk-exemplo-de-customiza), nas linha 21 usamos o código no IF para testar se o submit era do tipo "Salvar".

##### Mensagem e alerta para o usuário

No código abaixo mostra exemplo de como apresentar alertas na tela para o usuário.

```JavaScript
//mensagem de sucesso
pageMsg.showMsgSuccess(msg, title);

//mensagem de aviso
pageMsg.showMsgWarning(msg, title);

//mensagem de erro
pageMsg.showMsgError(msg, title);

//esconder a mensagem 
pageMsg.hideMsgs(true);
```

##### Recuperar um valor de uma QueryString

```JavaScript
var value = getQuerystring('paramQuerystring1');
```

**Você também pode usar o javascript nativo, detalhado nesse exemplo: [Como Obter Parâmetros da Query String com JavaScript](https://wiki.agilityflow.io/books/manual-de-customiza%C3%A7%C3%A3o/page/como-obter-parametros-da-query-string-com-javascript "Como Obter Parâmetros da Query String com JavaScript")**

#####   


#### Javascript - Formulário Filho

##### Javascript - Buscar o Json com o resultado e todos os campos de uma tabela filha

```JavaScript
//o parametro 'f43330be-0467-7fee-1168-28c9e6d185f0' é o Id da Tabela
var json = formContext.childForm.datatable.getResultJson('f43330be-0467-7fee-1168-28c9e6d185f0');
```

##### Javascript - Atualizar uma Tabela Filha

```JavaScript
//o parametro 'f43330be-0467-7fee-1168-28c9e6d185f0' é o Id da Tabela
formContext.childForm.datatable.refresh('f43330be-0467-7fee-1168-28c9e6d185f0');
```

##### Javascript - Buscar o total de itens em uma tabela filha

```JavaScript
//o parametro 'f43330be-0467-7fee-1168-28c9e6d185f0' é o Id da Tabela
var total = formContext.childForm.datatable.totalRows('f43330be-0467-7fee-1168-28c9e6d185f0');
```

##### Javascript - Refazer a ordenação dos itens quando a tabela filha estiver liberada a ordenação manual via "Drag and Drop" (Arrastar e soltar)

```JavaScript
//reordena os itens da tabela filha de acordo com a ordem dos ids passados no parametro @items_sorted
//o primeiro parametro, 'f43330be-0467-7fee-1168-28c9e6d185f0' é o Id da Tabela
// o segundo parametro "items_sorted" é a lista ordenada com os ids dos elementos que pertencem a tabela:
//[
//    { formid: '', draftid: '' },
//    { formid: '', draftid: '' },
//    { formid: '', draftid: '' },
//]
formContext.childForm.datatable.setOrder('f43330be-0467-7fee-1168-28c9e6d185f0', items_sorted);
```

##### Javascript - Buscar todos os ids: "Id do Formulário" e "Id do Rascunho" dos itens listados em uma tabela filha

```JavaScript
//o parametro 'f43330be-0467-7fee-1168-28c9e6d185f0' é o Id da Tabela
var ids = formContext.childForm.datatable.getAllChildIds('f43330be-0467-7fee-1168-28c9e6d185f0');


o restorno será nesse formato:
 [
    {
        "formid": "5451ae4e-290a-4887-8099-6e9a026c0283",
        "draftid": ""
    },
    {
        "formid": "6c55eeef-427b-40ce-b415-dab11b4aa039",
        "draftid": ""
    },
    {
        "formid": "304cc8e2-47af-44d4-ba83-c0e4939e21fb",
        "draftid": ""
    }
]
```

##### Javascript - Disparo de Eventos na tabela Filha


<table border="1" id="bkmrk-objeto%E2%A0-nome-%2F-even" style="border-collapse: collapse; width: 100%; height: 150px;"><tbody><tr style="height: 30px;"><td style="width: 33.3333%; height: 30px;">**Objeto** </td><td style="width: 33.3333%; height: 30px;">**Nome / evento**</td><td style="width: 33.3333%; height: 30px;">**Exemplo de uso**</td></tr><tr style="height: 30px;"><td style="width: 33.3333%; height: 30px;">Tabela de Dados do Formulário Filho. Que fica no Formulário Pai.</td><td style="width: 33.3333%; height: 30px;">before-data-load

/

**Dispara antes de carregar os dados na tabela**

</td><td style="width: 33.3333%; height: 30px;">//id = id da tabela filha  
$('#id').on('before-data-load', function (e) {  
console.log('evento disparado antes de carregar os dados')  
});  
  
</td></tr><tr style="height: 30px;"><td style="width: 33.3333%; height: 30px;">Tabela de Dados do Formulário Filho. Que fica no Formulário Pai.</td><td style="width: 33.3333%; height: 30px;">data-loaded

/

**Dispara depois de carregar os dados na tabela**

</td><td style="width: 33.3333%; height: 30px;">//id = id da tabela filha  
$('#id').on('data-loaded', function (e, result\_json) {  
console.log('evento disparado depois de carregar os dados')  
console.log('result\_json',result\_json)  
});</td></tr><tr style="height: 30px;"><td style="width: 33.3333%; height: 30px;"> </td><td style="width: 33.3333%; height: 30px;"> </td><td style="width: 33.3333%; height: 30px;"> </td></tr><tr style="height: 30px;"><td style="width: 33.3333%; height: 30px;"> </td><td style="width: 33.3333%; height: 30px;"> </td><td style="width: 33.3333%; height: 30px;"> </td></tr></tbody></table>

##### **<span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu, Roboto, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal;">Javascript - </span><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu, Roboto, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal;">Biblioteca</span>**

<span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu, Roboto, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400;">Abaixo estão listadas as biblioteca javascript que já estão importadas na página do formulário:</span>

<table border="1" cellpadding="0" cellspacing="0" dir="ltr" id="bkmrk-asrange%2Fjquery-asran" style="height: 545px;"><colgroup><col width="341"></col></colgroup><tbody><tr style="height: 31px;"><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":2,"2":"bootstrap-daterangepicker/daterangepicker.js"}" style="height: 31px; width: 341px;">bootstrap-daterangepicker/daterangepicker.js</td></tr><tr style="height: 31px;"><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":2,"2":"bootstrap-daterangepicker/moment.min.js"}" style="height: 31px; width: 341px;">bootstrap-daterangepicker/moment.min.js</td></tr><tr style="height: 31px;"><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":2,"2":"bootstrap-select/bootstrap-select.js"}" style="height: 31px; width: 341px;">bootstrap-select/bootstrap-select.js</td></tr><tr style="height: 31px;"><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":2,"2":"bootstrap/bootstrap.js"}" style="height: 31px; width: 341px;">bootstrap/bootstrap.js</td></tr><tr style="height: 31px;"><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":2,"2":"guid.js"}" style="height: 31px; width: 341px;">guid.js</td></tr><tr style="height: 49px;"><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":2,"2":"jquery.inputmask/4.0.0-beta.19/jquery.inputmask.bundle.js"}" style="height: 49px; width: 341px;">jquery.inputmask/4.0.0-beta.19/jquery.inputmask.bundle.js</td></tr><tr style="height: 31px;"><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":2,"2":"jquery.mask.js"}" style="height: 31px; width: 341px;">jquery.mask.js</td></tr><tr style="height: 31px;"><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":2,"2":"jquery.maskMoney.js"}" style="height: 31px; width: 341px;">jquery.maskMoney.js</td></tr><tr style="height: 31px;"><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":2,"2":"jquery.validate.js"}" style="height: 31px; width: 341px;">jquery.validate.js</td></tr><tr style="height: 31px;"><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":2,"2":"jquery.webui-popover.js"}" style="height: 31px; width: 341px;">jquery.webui-popover.js</td></tr><tr style="height: 31px;"><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":2,"2":"jquery/jquery.js"}" style="height: 31px; width: 341px;">jquery/jquery.js</td></tr></tbody></table>

### Criar Html (Componente Cshtml): 

Abra o formulário que deseja customizar. Na barra superior desse formulário clique em **"Visual Code Editor"** como mostra figura abaixo:

![](http://wiki.agilityflow.io/uploads/images/gallery/2019-03-Mar/scaled-840-0/image-1553004288897.png)

Para criar um html, clique no botão "**Novo Cshtml**", como na figura abaixo:

![](http://wiki.agilityflow.io/uploads/images/gallery/2019-03-Mar/scaled-840-0/image-1553004348942.png)

Ao clicar, digite o nome do Html

![](http://wiki.agilityflow.io/uploads/images/gallery/2019-03-Mar/scaled-840-0/image-1553009985544.png)

Agora o novo html está criado, e será mostrado para edição no menu do lado esquerdo, como na imagem abaixo.

![](http://wiki.agilityflow.io/uploads/images/gallery/2019-03-Mar/scaled-840-0/image-1553010026218.png)

Clique no nome do Html para edita-lo.

No arquivo Html, é possível utilizar qualquer tag Html que você precisar. Para embelezar o seu html utilize a linguagem css na área "[Style (CSS)](http://wiki.agilityflow.io/link/78#bkmrk-style-%28css%29)", e para customizar com javascript, faça as customizações na área "<a>Javascript</a>".

Faça as edições necessárias, salve e posicione esse novo componente no seu formulário. (O passo a passo para posicionar o componente no formulário está descrito mais abaixo)

##### Posicionando o componente Html no formulário

Depois de [criado](http://wiki.agilityflow.io/link/78#bkmrk-html-%28componente-csh) o componente cshtml, salve todas as configurações e customizações realizadas no Visual Code Editor, através do botão ![](http://wiki.agilityflow.io/uploads/images/gallery/2019-03-Mar/scaled-840-0/image-1553010407195.png).

Agora volte para a edição do formulário e clique no botão ![](http://wiki.agilityflow.io/uploads/images/gallery/2019-03-Mar/scaled-840-0/image-1553010476873.png)

![](http://wiki.agilityflow.io/uploads/images/gallery/2019-03-Mar/scaled-840-0/image-1553010465419.png)

No box de opções de campos, o seu componente "ExemploHtml" já deverá estar listado, como mostra a imagem abaixo:

![](http://wiki.agilityflow.io/uploads/images/gallery/2019-03-Mar/scaled-840-0/image-1553010542585.png)

Clique no nome do componente, e logo em seguida em salvar ![](http://wiki.agilityflow.io/uploads/images/gallery/2019-03-Mar/scaled-840-0/image-1553010646477.png)

Agora você deve posiciona-lo na tela, para isso basta clicar na opção ![](http://wiki.agilityflow.io/uploads/images/gallery/2019-03-Mar/scaled-840-0/image-1553010738286.png) como mostra imagem abaixo.

![](http://wiki.agilityflow.io/uploads/images/gallery/2019-03-Mar/scaled-840-0/image-1553010465419.png)

Ao abrir a opção de montagem de tela, posicione e arraste o seu componente onde você preferir.

Agora salve e publique esse novo formulário! Pronto, o seu componente está criado.

### Exemplo prático de customização html

No exemplo a seguir vamos apresentar uma mensagem em azul de bom dia ou boa tarde ou boa noite dependendo do horário atual.

Para descobrir qual a data e qual a mensagem a ser apresentada, usamos C# no cshtml.

Para deixar a mensagem azul, usamos CSS.

Nesse exemplo não utilizamos javascript para nenhuma ação, mas poderia ser utilizado caso fosse necessário.

##### Passo 1 - Definir o html

Crie o cshtml como descrito [aqui.](http://wiki.agilityflow.io/link/78#bkmrk-html-%28componente-csh)

Agora cole o código abaixo nesse novo html:

```C++
@{
    string parteDoDia;
    var hours = DateTime.Now.Hour;
    if (hours > 16)
    {
        parteDoDia = "Boa noite";
    }
    else if (hours > 11)
    {
        parteDoDia = "Boa tarde";
    }
    else
    {
        parteDoDia = "Bom dia";
    }
}

<div class="painel-msg-customizada">        
    <span>@parteDoDia,</span>
</div>
```

##### Passo 2 - Definir o CSS

Entre na área de CSS e cole o código abaixo:

```CSS
.painel-msg-customizada{
    display: block;
    text-align: left;
    padding-top: 10px;
}

.painel-msg-customizada span{

    color: #0281ff;
    display: block;
    font-size: 17px;
    font-weight: 500;
    border-bottom: solid 2px #a4d2ff;
    margin-bottom: 15px;
}
```

##### Passo 3 - Posicionar o html no formulário

Salve tudo no Visual Code Editor e posicione esse componente html, como descrito [aqui](http://wiki.agilityflow.io/link/78#bkmrk-depois-de-criado-o-c).

##### Passo 4 - Salvar e publicar o formulário

Salve e publico o novo formulário.

Agora acesse esse formulário, o resultado deve ser igual ao print abaixo:

![](http://wiki.agilityflow.io/uploads/images/gallery/2019-03-Mar/scaled-840-0/image-1553014672823.png)

#### C# no componente CSHTML 

Se você precisar de alguma informação do formulário, utilize a opção abaixo

##### C# - Propriedades

<table border="1" id="bkmrk-bool-israscunho-%7Bget"><tbody><tr><td>string FormId</td><td>Id do registro, pode ser em branco ou nulo qdo for um rascunho</td></tr><tr><td>bool IsRascunho {get;}</td><td>Retorna true caso a linha seja um Rascunho</td></tr><tr><td>string DraftId</td><td>Id do rascunho</td></tr></tbody></table>


##### C# - Recuperar (Get) valor dos campos

<table border="1" id="bkmrk-string-getvalue%28stri" style="height: 281px;"><tbody><tr style="height: 37px;"><td style="width: 340px; height: 37px;">string GetValue(string idColuna)</td><td style="width: 469px; height: 37px;">retorna o valor do campo

</td></tr><tr style="height: 109px;"><td style="width: 340px; height: 109px;">int? GetInt(string idColuna)</td><td style="width: 469px; height: 109px;">Retorna o valor do campo no tipo INT (inteiro), caso esse campo no formulário seja um número, se o valor for 10.000,99

Será retornado: 10000

</td></tr><tr style="height: 73px;"><td style="width: 340px; height: 73px;">decimal? GetDecimal(string idColuna)</td><td style="width: 469px; height: 73px;">Retorna o valor do campo no tipo Decimal, caso esse campo no formulário seja um número, se o valor for 10.000,99 Será retornado: 10000.99

</td></tr><tr style="height: 31px;"><td style="width: 340px; height: 31px;">DateTime? GetDateTime(string idColuna)</td><td style="width: 469px; height: 31px;">Retorna o valor do campo no tipo DateTime </td></tr><tr style="height: 31px;"><td style="width: 340px; height: 31px;"><div><div>Guid? GetGuid(string idColuna)</div></div></td><td style="width: 469px; height: 31px;">Retorna o valor do campo no tipo Guid </td></tr><tr><td style="width: 340px;"><div><div>string GetText(string idColuna)</div></div></td><td style="width: 469px;"><div><div>No caso de campos que são Lista Dinanica, exemplo Combo, Auto completo, radio etc.</div><div>  
</div><div>No Json de Campos Preenchidos no Formulario, só terá o Value dos campos</div><div>  
</div><div>Esse método retornará o Texto desse campo.</div><div>  
</div><div>Exemplo:</div><div>  
</div><div>Existe no formulário um campo chamado 'Produto', com o id definido como 'produto'.</div><div>  
</div><div>Esse campo é do tipo 'AutoComplete' e listará os 'Produtos' por 'Nome'.</div><div>  
</div><div>Quando o usuário salvar o formulário, no Json de envio não retornará o Nome do Produto, apenas o Id do produto selecionado (Esse id estará no formato de um GUID).</div><div>  
</div><div>Para recuperar o Nome do produto, vc precisará executar esse método da seguinte forma:</div>  
<div>var nomeProduto = PageContext.GetText("produto")</div></div></td></tr></tbody></table>

<table border="1" id="bkmrk-vari%E3%A1vel-tipo-%E2%A0-fo" style="width: 966px; height: 2248px;"><tbody><tr style="height: 31px;"><td style="width: 279px; height: 31px;">**Variável**</td><td style="width: 111px; height: 31px;">**Tipo**</td><td style="width: 576px; height: 31px;"> </td></tr><tr style="height: 613px;"><td style="width: 279px; height: 613px;"><span style="color: #ff00ff;">(**deprecated)**</span>

<span style="text-decoration: line-through;">Model.FormularioCamposPreenchidos</span>

</td><td style="width: 111px; height: 613px;"><span style="text-decoration: line-through;"><span style="color: #ff00ff;">(**deprecated)**</span></span>

<span style="text-decoration: line-through;">dynamic (Json)</span>

</td><td style="width: 576px; height: 613px;"><span style="color: #ff00ff;">(**deprecated**: utilizar o método PageContext.GetValue descrito mais acima)</span>

<span style="text-decoration: line-through;">Retorna um json com os campos preenchidos no formulário, exemplo:</span>

<span style="text-decoration: line-through;">{</span>

<span style="text-decoration: line-through;"> "campo1": "xxxxx",</span>

<span style="text-decoration: line-through;"> "campo2": "yyyyy",</span>

<span style="text-decoration: line-through;"> "campo3": "zzzzz",</span>

<span style="text-decoration: line-through;">}</span>

<span style="text-decoration: line-through;">Para resgatar a informação do campo1, utilize:</span>

```C#
@{
   var campo1 = Model.FormularioCamposPreenchidos["campo1"];
}
<div>
   @campo1
</div>
```

<span style="text-decoration: line-through;">Para resgatar o id do formulário, utilize:</span>

```C#
@{	
    var idFormulario_Forma1 = Model.Id;
    var idFormulario_Forma2 = Model.FormularioCamposPreenchidos["id"];
}

<div>@idFormulario_Forma1</div>
<div>@idFormulario_Forma2</div>
```

</td></tr><tr style="height: 200px;"><td style="width: 279px; height: 200px;"><span style="color: #ff00ff;">(**deprecated)**</span>

<span style="text-decoration: line-through;">Model.Id</span>

<span style="text-decoration: line-through;">OU </span>

<span style="text-decoration: line-through;">Model.FormularioCamposPreenchidos\["id"\];</span>

</td><td style="width: 111px; height: 200px;"><span style="color: #ff00ff;">(**deprecated)**</span>

<span style="text-decoration: line-through;">Guid</span>

<span style="text-decoration: line-through;">OU</span>

<span style="text-decoration: line-through;">string</span>

</td><td style="width: 576px; height: 200px;"><span style="color: #ff00ff;">(**deprecated)**</span>

<span style="text-decoration: line-through;">Para resgatar o id do formulário, utilize:</span>

```C#
@{	
    var idFormulario_Forma1 = Model.Id;
    var idFormulario_Forma2 = Model.FormularioCamposPreenchidos["id"];
}

<div>@idFormulario_Forma1</div>
<div>@idFormulario_Forma2</div>

```

</td></tr><tr style="height: 200px;"><td style="width: 279px; height: 200px;">Model.FormularioTemporarioId

</td><td style="width: 111px; height: 200px;">Guid

</td><td style="width: 576px; height: 200px;">Para resgatar o id temporario do formulário, utilize:

```C#
@{	
    var formularioTemporarioId = Model.FormularioTemporarioId;
}

<div>@formularioTemporarioId </div>

```

</td></tr><tr style="height: 37px;"><td style="width: 279px; height: 37px;"><span style="color: #ff00ff;">(**deprecated)**</span>

<span style="text-decoration: line-through;">Model.RascunhoId</span>

</td><td style="width: 111px; height: 37px;"><span style="color: #ff00ff;">(**deprecated)**</span>

<span style="text-decoration: line-through;">Guid</span>

</td><td style="width: 576px; height: 37px;"><span style="color: #ff00ff;">(**deprecated)**</span>

<span style="text-decoration: line-through;">Para resgatar o id do rascunho, caso seja um</span>

</td></tr><tr style="height: 37px;"><td style="width: 279px; height: 37px;">Model.EstruturaFormularioId

</td><td style="width: 111px; height: 37px;">Guid

</td><td style="width: 576px; height: 37px;">Para resgatar o id da ESTRUTURA do formulário

</td></tr><tr style="height: 200px;"><td style="width: 279px; height: 200px;">**Quando estiver dentro do Formulário Filho:**

Model.FormularioIdPai

</td><td style="width: 111px; height: 200px;">Guid

</td><td style="width: 576px; height: 200px;">Para resgatar o id do formulário pai, quando estiver dentro de um formulário filho, utilize:

```C#
@{	
    var formularioIdPai= Model.FormularioIdPai;
}

<div>@formularioIdPai</div>
```

</td></tr><tr style="height: 200px;"><td style="width: 279px; height: 200px;">**Quando estiver dentro do Formulário Filho:**

Model.FormularioTemporarioIdPai

</td><td style="width: 111px; height: 200px;">Guid

</td><td style="width: 576px; height: 200px;">Para resgatar o id temporário do formulário pai, quando estiver dentro de um formulário filho, utilize:

```C#
@{	
    var formularioTemporarioIdPai= Model.FormularioTemporarioIdPai;
}

<div>@formularioTemporarioIdPai</div>

```

</td></tr><tr style="height: 200px;"><td style="width: 279px; height: 200px;">**Quando estiver dentro do Formulário Filho:**

Model.EstruturaFormularioIdPai

</td><td style="width: 111px; height: 200px;">Guid

</td><td style="width: 576px; height: 200px;">Para resgatar o id temporário do formulário pai, quando estiver dentro de um formulário filho, utilize:

```C#
@{	
    var estruturaFormularioIdPai= Model.EstruturaFormularioIdPai;
}

<div>@estruturaFormularioIdPai</div>
```

</td></tr><tr style="height: 241px;"><td style="width: 279px; height: 241px;"><div><div>WFS.Common.AppSettings.StaticFilePath</div></div></td><td style="width: 111px; height: 241px;">string</td><td style="width: 576px; height: 241px;">Retorna a url dos arquivos estaticos do agilityflow, exemplo, .js, .css, etc..

caso queira importar um arquivo JS que já exista na biblioteca de arquivos estaticos do agilityflow

<div><div>&lt;script src="**@WFS.Common.AppSettings.StaticFilePath**/js/xxxxx/yyyyyy.js?**@WFS.Common.AppSettings.StaticFileVersion**"&gt;&lt;/script&gt;</div></div></td></tr><tr style="height: 289px;"><td style="width: 279px; height: 289px;"><div><div>WFS.Common.AppSettings.StaticFileVersion</div></div></td><td style="width: 111px; height: 289px;">string</td><td style="width: 576px; height: 289px;">Utilize essa variável para limpar o cache do seu arquivo estático, sendo assim coloque ela como parametro de querystring do seu arquivo, exemplo:

caso queira importar um arquivo JS que já exista na biblioteca de arquivos estaticos do agilityflow

<div><div>&lt;script src="@WFS.Common.AppSettings.StaticFilePath/js/xxxxx/yyyyyy.js?**@WFS.Common.AppSettings.StaticFileVersion**"&gt;&lt;/script&gt;</div></div></td></tr></tbody></table>


#### C# no Componente CSHTML - Testar se é umnovo formulário ou se é uma edição 

Para saber se o formulário é um novo ou está para edição, apenas teste a variável de ID, como no exemplo abaixo:

Forma 1

```C#
@{
  var isNovoFormulario = GuidHelper.IsNullOrEmpty(Model.Id);
}
```

Forma 2

```C#
@{
var isNovoFormulario = Model.Id.IsNullOrEmpty();
}
```

Exemplo

```C#
@{
  	var msg = "";
  	var formularioId = Model.Id;

    if(formularioId.IsNullOrEmpty()){
      msg = "é um novo formulario";
    }else{
      msg = "NÃO é um novo formulario";
    }    
  
}
<div>@msg</div>
```

#### C# no componente CSHTML - Testar se é um rascunho

```C#
@{
  	var msg = "";
  	var rascunhoId = Model.RascunhoId;

    if(rascunhoId.IsNullOrEmpty()){
      msg = "é um Rascunho";
    }else{
      msg = "NÃO é um Rascunho";
    }    
  
}
<div>@msg</div>
```

### Criar uma Tabela de dados customizada através de programação: Query SQL, C#, HTML e CSS: 

Abaixo está um exemplo de criação de uma tabela de dados buscando as informações através de uma Query SQL e apresentando no Html:

Para customizar o CSS e Javascript da tabela de dados, utilize áreas de customização já citadas nos itens acima

```C#
<h5 id="datatableTitle">Tasks</h5> 
<a id="btnAdd" href="javascript:pageNavigation.openSimpleLightBox({  islookup: true, url:'@Model.GetBaseUrl()/fluxo/index/7f786f15-d644-4351-8763-46bc2923fd21' })"><i class="mdi mdi-plus"></i> Add task</a>
<table id="tasksTable" border="1">

                <tr>
                    <th width="140px">Status</th>
                    <th>Team</th>
                    <th>Description</th>
                    <th>CreatedDate</th>
                    <th>ModifiedDate</th>
                </tr>

@{
    var applicationId = PageContext.FormId;
    
    /* concatenando o parametro */
    var dt = await PageContext.GetDataTableAsync(@"select 
                                        isnull(task.id,'') TaskId,
                                        isnull(task.description,'') TaskDescription,
                                        isnull(team.name,'') Team,
                                        task.log_data_criacao CreatedDate,
                                        task.log_data_alteracao ModifiedDate,
                                        isnull(etp.etp_nome,'') CurrentStep,
                                        frm_status_fluxo StatusFlow
                                        from 
                                            x_tbl_application_task2 task
                                        inner join tbl_formulario form
                                            on task.id = form.frm_id
                                        left join tbl_formulario_etapa etp
                                            on form.etp_id_atual = etp.etp_id and etp.frm_id = form.frm_id
                                        left join x_tbl_team team 
                                            on task.team = team.id

                                        where 
                                        task.deletado = 0
                                        and task.id_application = '"+applicationId+"' order by  task.log_data_alteracao desc, task.log_data_criacao desc ");
    
    
    /* passando como parametro */
    /*var paramsQuery = new List<NpgsqlParameter>();
    paramsQuery.Add(new NpgsqlParameter("@applicationId", applicationId){ NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Uuid });
    var dt = await PageContext.GetDataTableAsync(@"select 
                                        isnull(task.id,'') TaskId,
                                        isnull(task.description,'') TaskDescription,
                                        isnull(team.name,'') Team,
                                        task.log_data_criacao CreatedDate,
                                        task.log_data_alteracao ModifiedDate,
                                        isnull(etp.etp_nome,'') CurrentStep,
                                        frm_status_fluxo StatusFlow
                                        from 
                                            x_tbl_application_task2 task
                                        inner join tbl_formulario form
                                            on task.id = form.frm_id
                                        left join tbl_formulario_etapa etp
                                            on form.etp_id_atual = etp.etp_id and etp.frm_id = form.frm_id
                                        left join x_tbl_team team 
                                            on task.team = team.id

                                        where 
                                        task.deletado = 0
                                        and task.id_application = @applicationId order by  task.log_data_alteracao desc, task.log_data_criacao desc ", paramsQuery.ToArray());*/



    foreach (DataRow dr in dt.Rows)
    {

            var ModifiedDate = dr["ModifiedDate"] == DBNull.Value ? "" : dr["ModifiedDate"].ToString();
            var currentStep = dr["CurrentStep"].ToString();
            var statusFlow = dr["StatusFlow"].ToString();

            if(statusFlow == "A"){
                currentStep = "APPROVED";
            }else if(statusFlow == "X"){
                currentStep = "REJECTED";
            }

            <text>
                <tr class="task-row status-@currentStep" data-taskid='@dr["TaskId"].ToString()'>
                    <td><span class="st">@currentStep</span></td>
                    <td>@dr["Team"].ToString()</td>
                    <td>@dr["TaskDescription"].ToString()</td>
                    <td>@dr["CreatedDate"].ToString()</td>
                    <td>@dr["ModifiedDate"].ToString()</td>
                </tr>
            </text>

    }

}
</table>
```

### [![ezgif.com-video-to-gif.gif](https://wiki.agilityflow.io/uploads/images/gallery/2020-05-May/ezgif.com-video-to-gif.gif)](https://wiki.agilityflow.io/uploads/images/gallery/2020-05-May/ezgif.com-video-to-gif.gif)

### Recarregar no servidor um componente Html ao alterar uma determinada informação do formulário:

Você pode determinar alguns momentos para que as informações de um componente html sejam recarregadas do servidor.

Essa é uma opção vantajosa em situações em que você tenha consultas (queries) de banco de dados no dentro do componente Html e deseja que essa consulta seja atualizada em alguns momentos.

<p class="callout info">Apenas campos do tipo "Lista de seleção (Combo)" e "Pesquisa com auto completar" poderão disparar o recarregamento do Componente Cshtml</p>

##### Exemplo para recarregar o componente cshtml

Suponhamos que você crie um formulário que contenha 2 campos, o **primeiro** é um combo de **Perfil de Acesso** no sistema e o **segundo** campo é um componente CsHtml que contenha uma **tabela que mostre todos os usuários** que possuam o perfil selecionado no **primeiro** campo de **Perfil de Acesso**. Então, todas vez que o campo **Perfil de acesso** for alterado, a tabela de usuários deve ser recarregada para mostrar só os usuários relacionados ao novo perfil alterado.

Para esse exemplo, crie um novo formulário. Nesse novo formulário, crie um combo chamado **Perfil** e abaixo crie um componente CShtml que apresente uma tabela com todos os usuários do perfil selecionado (copiar e colar código abaixo no novo componente).

Código para o Componente Cshtml que listará os usuários

```C#
<h5 id="datatableTitle">Usuários com esse perfil:</h5> 
<table id="usuTable" border="1">

                <tr>
                    <th width="140px">Nome</th>
                    <th>E-mail</th>
                </tr>

@{
    var perfilId = Model.FormularioCamposPreenchidos["perfil"];

    if(perfilId != null && perfilId.ToString() != string.Empty){

        //na query será utilizado no WHERE o id do perfil selecionado no combo
        var query = @"select id, isnull(usu_nome,'') Nome, isnull(usu_email,'') Email  from tbl_usuario u inner join tbl_perfil_usuario pu on u.id = pu.id_tbl_usuario and pu.deletado = 0 where u.deletado = 0 and pu.id_tbl_perfil = '"+perfilId+"' ";
        var dt = await PageContext.GetDataTableAsync(query);

        foreach (DataRow dr in dt.Rows)
        {

                <text>
                    <tr class="task-row" data-taskid='@dr["id"].ToString()'>
                        <td>@dr["Nome"].ToString()</td>
                        <td>@dr["Email"].ToString()</td>
                    </tr>
                </text>

        }

    }

}
</table>
```

Agora adicione esse componente na tela abaixo do campo Perfil.

Clique para editar o componente e marque o checkbox "Ao alterar o campo Perfil", como na imagem abaixo.

![](https://wiki.agilityflow.io/uploads/images/gallery/2020-05-May/scaled-840-0/image-1588955959793.png)

Pronto, agora salve e acesse esse novo formulário criado.

Tente alterar o valor do combo Perfil, se tudo correr bem a tabela de usuários deverá ser recarregada toda vez que o campo perfil for alterado.

[![ezgif.com-video-to-gif.gif](https://wiki.agilityflow.io/uploads/images/gallery/2020-05-May/ezgif.com-video-to-gif.gif)](https://wiki.agilityflow.io/uploads/images/gallery/2020-05-May/ezgif.com-video-to-gif.gif)

#### C# - Adicionar e Atualizar os itens a uma tabela de formulário filho:

Para esse exemplo, será necessário Associar um Formulário Filho a um Formulário Pai, considere que nesse exemplo o Formulário Filho tenha um campo de texto chamado "nome\_filho".

O exemplo abaixo foi colocado dentro de um cshtml do formulário pai e ao criar um novo formulário adicionará um item ao formulário filho e logo em seguida atualizará o item apenas para a demonstração das funções

<p class="callout info">Caso a informação a ser adicionada ou atualizada seja um número, enviar sem separador de milhar e o separador de decimal deve ser "." (ponto), exemplo: para o valor de nove mil e quinhentos, deve ser enviado 9500.00. Para facilitar utilize a função **PageContext.FormatNumberToString\_EnglishFormat(999999.99, 2);**</p>

```C#
@{	

	//id da tabela
    var tableid_relacaoFormularioPaiFilhoId = Guid.Parse("0dd874a9-9c39-4e4f-acc3-02015a60f6bb"); //table id DO FORMULÁRIO FILHO
  
    //info do formulario filho
    var campos_e_valores = new DataDictionary();
    campos_e_valores["nome_filho"] = "Exemplo 01 - " + DateTime.Now;
    campos_e_valores["valor_numerico"] = PageContext.FormatNumberToString_EnglishFormat(999999.99, 2);
  
  
	//testa se é um form NOVO e se NÂO é RASCUNHO pois nesse exemplo quero inserir apenas para formulário NOVOS que não sejam RASCUNHOs
    var isNovo = Model.Id.IsNullOrEmpty();
    var isRascunho = !Model.RascunhoId.IsNullOrEmpty();
  
  
    if(isNovo && !isRascunho){
      
      	//adiciona na tabela filha
       //retorna o id do rascunho desse formlario filho, pois o ID final só será gerado ao Salvar o Formulario PAi
       var formRascunhoId = PageContext.AddChildForm( tableid_relacaoFormularioPaiFilhoId, campos_e_valores);
      
      
      
        //atualiza o item que acabamos de adicionar, apenas para demonstração
		Guid? idFormularioFilho = null;        
        campos_e_valores["nome_filho"] = "Exemplo Atualizado 0123456789 - " + DateTime.Now;            
        PageContext.UpdateChildForm(         	         
            //se ainda não foi salvo pela primeira vez, o item só terá o Id do Rascunho
            rascunhoId, 

            //se já foi salvo pela primeira vez, o item já terá o Id
            //então passa aqui o id (nesse exemplo estamos passando null para atualizar apenas o
            idFormularioFilho, 

            tableid_relacaoFormularioPaiFilhoId,
            campos_e_valores);
     
	}
}


```

#### C# - Obter o total de itens em uma tabela de formulário filho:

```C#
@{	
	//relacaoFormularioPaiFilhoId não é o id do formulario filho e sim o id do campo que gera ao adicionar o formulario filho ao formulario pai
    var relacaoFormularioPaiFilhoId = Guid.Parse("f43330be-0467-7fee-1168-28c9e6d185f0"); //trocar esse id 
  
    var total = await PageContext.CountChildFormsAsync(relacaoFormularioPaiFilhoId);
}
```

#### C# - Enviar e Recuperar parâmetros extras na requisição ajax no partial view (cshtml)

Enviando um parâmetro extra via javascript

```JavaScript
var idsItensPrecosCompostos = formContext.childForm.datatable.getAllChildIds('251c66c9-cb26-f3a8-d014-8a1dd4a6b6aa')
formContext.loadViewComponent("calcular_valor_custo_preco_composto", {
  extraData: { idsItensPrecosCompostos: JSON.stringify(idsItensPrecosCompostos) } ,
  onSuccess: function (response) {
	console.log(response)
  }
})
```

Recuperando um parâmetro extra via C# no CShtml.

Nesse exemplo, dentro do partial view "**calcular\_valor\_custo\_preco\_composto**", colocaremos esse código

```C#
@{
    
    var json_idsItensPrecosCompostos = Request["idsItensPrecosCompostos"];
    

}
<div>@json_idsItensPrecosCompostos</div>
```

#### C# e Javascript - Trabalhando com Json 

1\. Enviando um parâmetro no formato JSON via Javascript. Para isso no código abaixo transformamos um Array em JSON usando o JSON.stringify(...)

```JavaScript
var idsItensPrecosCompostos = formContext.childForm.datatable.getAllChildIds('251c66c9-cb26-f3a8-d014-8a1dd4a6b6aa')
formContext.loadViewComponent("calcular_valor_custo_preco_composto", {
  extraData: { idsItensPrecosCompostos: JSON.stringify(idsItensPrecosCompostos) } ,
  onSuccess: function (response) {
	console.log(response)
  }
})
```

2\. Recuperando um parâmetro JSON via C# e convertendo em Objeto Json

Você poderá utilizar qualquer função que faça parte das Bibliotecas

<table border="1" id="bkmrk-newtonsoft.json-newt" style="border-collapse: collapse; width: 100%;"><tbody><tr><td style="width: 100%;">Newtonsoft.Json</td></tr><tr><td style="width: 100%;">Newtonsoft.Json.Linq</td></tr></tbody></table>

Nesse exemplo, dentro do partial view "**calcular\_valor\_custo\_preco\_composto**", colocaremos esse código para transformar o parametro que era string em um objeto dinamico do tipo JSON:

```C#
@{
    
    var json_idsItensPrecosCompostos = Request["idsItensPrecosCompostos"];    
    dynamic idsItensPrecosCompostos = Newtonsoft.Json.JsonConvert.DeserializeObject(json_idsItensPrecosCompostos);
}

```

3\. Count no JSON

\* o count vai existir em caso do JSON estar no formato de uma lista ( array ).

```C#
@{
    
    var json_idsItensPrecosCompostos = Request["idsItensPrecosCompostos"];    
    dynamic idsItensPrecosCompostos = Newtonsoft.Json.JsonConvert.DeserializeObject(json_idsItensPrecosCompostos);
  	var total = idsItensPrecosCompostos.Count;
}

```

4\. Looping no JSON

\* o foreach vai existir em caso do JSON estar no formato de uma lista ( array ).

```C#
@{
    
    var json_idsItensPrecosCompostos = Request["idsItensPrecosCompostos"];    
    dynamic idsItensPrecosCompostos = Newtonsoft.Json.JsonConvert.DeserializeObject(json_idsItensPrecosCompostos);

    var draftids = new List<string>();
    var formids = new List<string>();
    foreach (var idItem in idsItensPrecosCompostos)
    {
        draftids.Add(idItem.draftid.ToString());
        formids.Add(idItem.formid.ToString());
    }
}

```

#### C# - Transformar Array List em uma string separada por virgula

```C#
@{	
    var itens = new List<string>() { "abacaxi", "mamão", "melão", "banana"};
    var msg = String.Join(",",itens.ToArray());
}
@msg
```

#### C# - Criar um Json dinamicamente

```C#
@{	
    var list_InfoNomeEmail = new JArray() as dynamic; 
    
  	var query = @"select nome, email from x_tbl_xxxxxxxxxxxxx where deletado = 0";
    var dt = await PageContext.GetDataTableAsync(query);
    foreach (DataRow dr in dt.Rows)
    {
      var nome = dr["nome"].ToString();
      var email = dr["email"].ToString();

      //cria o objeto e inclua na lista para depois ser transformado em json
      dynamic infoNomeEmail = new JObject();
      infoNomeEmail.nome = nome;
      infoNomeEmail.email = email;
      list_InfoNomeEmail.Add(infoNomeEmail);
    }
  
  
  //devolve os items em formato json
  if(list_InfoNomeEmail.Count > 0){
    
     //serializa para JSON
     var formata_para_json = JsonConvert.SerializeObject(list_InfoNomeEmail);
    
     //usa o Html.Raw para garantir a integridade dos caracteres no retorno
     @Html.Raw(formata_para_json)
  }

    
    
}

```