JSagon NodeJS Framework

Construa aplicações eficientes e escaláveis de maneira simples e rápida.


View

A view tem como propósito a exibição de dados e comportamentos visuais para o usuário. Em NodeJS, as View Engines são utilizadas para fornecer um mecanismo de renderização de página mais amplo e dinâmico, permitindo assim uma gama maior de possibilidades.

A View Engine utilizada pela JSagon Framework é a Handlebars por padrão. Porém, a mudança para outra Engine é completamente viável utilizando um dos adapters oficiais disponibilizados ou de maneira manual. Além do Handlebars, hoje possuímos compatibilidade oficial com EJS.

Para realizar a alteração da View Engine para o EJS, caso seja de interesse. Faça como a seguir.

Primeiro, será preciso instalar o seguinte módulo.

npm i @jsagon/view-engine-ejs

Agora, precisaremos fazer uma pequena mudança em nosso arquivo dev/src/server.ts passando a factory da View Engine como parâmetro à construção da aplicação, como no exemplo a seguir:

    import { JSagon } from '@jsagon/core'
    import { ViewEngineFactory } from '@jsagon/view-engine-ejs'
    import configApp from './config/app.config'
    
    JSagon.create(configApp, ViewEngineFactory).listen(3000, () => {
      console.log('Server online!')
    })

Obs.: caso trabalhe com outra View Engine, no final deste artigo será apresentado um meio de configurá-la manualmente.


Entendendo a estrtutura

Todas as views são armazenas em dev/resource/views.

A pasta layouts é onde se encontra o arcabouço das páginas. Nesta pasta se encontram a estrutura base e suas parciais em arquivos separados. Este modelo de estrutura que centraliza o layout evita que em cada página criada seja preciso adicionar sempre a mesma estrutura: cabeçalho, rodapé, menu, etc. Se tornando assim inviável a mudança ao longo do tempo.

Nesse modelo de estrutura em layouts, quando criamos um arquivo de página apenas com o conteúdo principal e ele é requisitado, automaticamente o seu conteúdo será inserido no conteúdo do layout, e será apresentado ao usuário.

Por padrão, o layout é divido nos seguintes arquivos:

main.hbs arquivo de layout base. Nele são importados os arquivos secundários, e tudo relacionado a css, javascript, entre outros, que será utilizado por toda a aplicação.
partials/header.hbs Arquivo que centraliza o cabeçalho da página.
partials/footer.hbs Arquivo que centraliza o rodapé da página.

A pasta dev/resource/views/app é onde serão criadas todas as páginas relacionadas a aplicação seguindo a hierarquia de pastas e convenção de nomes com base na estrutura do back-end.

Exemplo

Digamos que temos o seguinte controlador de nome ProdutoController no caminho a seguir: dev/src/app/FinancasApp/modules/ProdutoFin/Controller/ProdutoController.ts. Com este controlador implementando um método(action) interno de nome "cadastrar" que deverá mostrar uma tela de cadastro.

Caso um caminho não tenha sido explicitamente informado, a aplicação internamente seguindo a convenção de pastas e nomes, irá procurar a view no seguinte caminho: dev/resource/app/financas-app/produto-fin/produto/cadastrar.hbs. E irá renderizá-la de acordo com a explicação do layout.


Cada View Engine possui o seu próprio modelo de tratamento de dados. O que todas têm em comum, é que você pode transitar dados do seu controlador para a sua view.

Exemplo de passagem de dados do controlador para a view:

    import { ControllerBase, Request, Response } from '@jsagon/core'
     
    class ProdutoController extends ControllerBase {
    
    	public async detalheProduto(req: Request, res: Response) {
         return this.render({id:1, nome: 'Empresa ação 1', sobre: 'Ação para compra'})
      }
    
    }
    
    export default ProdutoController

O método render da classe ControllerBase define por padrão o caminho da view a ser renderizada.

Exemplo simplificado de utilização dos dados na View, arquivo detalhe-produto.hbs.

    <div>
      <div>Produto: {{nome}}</div>
      <div>Descrição: {{sobre}}</div>
    </div>

Para mais informações de como o Handlebars funciona, recomendo um estudo em sua documentação. O mesmo para o EJS.

Se por algum motivo não quiser utilizar layouts, como por exemplo para criação de uma landing page específica. Ou até mesmo se quiser utilizar outro layout ou definir uma outra view a ser utilizada. Faça como algum dos exemplos a seguir:

    import { ControllerBase, Request, Response } from '@jsagon/core'
     
    class ProdutoController extends ControllerBase {
    
        public async naoRenderizarLayout(req: Request, res: Response) {
            // Não renderiza o layout base definido
            return this.render({layout: false})
        }
    
    	public async alterarLayout(req: Request, res: Response) {
            // Altera o layout a ser utilizado. 
            return this.render({layout: 'caminho/do/layout.hbs'})
        }
    
    	public async alterarView(req: Request, res: Response) {
            // Não renderiza o layout. Caminho a partir de "views"
            return this.render({dados: {}}, 'caminho/da/view.hbs')
        }
    
    }
    
    export default ProdutoController

Definindo o layout por aplicação

Para definir um layout a ser utilizado por aplicação, é preciso apenas definir na configuração da aplicação o nome do layout em questão. No arquivo dev/src/app/NomeDaAplicacao/app.config.ts tire o comentário da opção "layout" e insira o nome desejado, como a seguir:

    module.exports = {
      ...
      // Layout file to be used - Layout a ser usado pelo app
      layout: 'nome-novo-layout'
    }

View Engine manual

Para as View Engines que a JSagon não possui adapters até o momento, é possível registrá-las da seguinte maneira:

    import { JSagon } from '@jsagon/core'
    import { ViewEngineFactory } from '@jsagon/view-engine-ejs'
    import configApp from './config/app.config'
    
    const bootstrap = JSagon.create(configApp, ViewEngineFactory)
    
    const app = bootstrap.getApplication().getApp()
    app.set('view engine', '...')
    app.use('...')
    
    bootstrap.listen(3000, () => {
      console.log('Server online!')
    })

O método getApp executado no exemplo anterior retorna a instancia da plataforma HTTP definida. Neste caso, a instância do Express.

Um passo a mais, aprofundando-se. Ir para Middlewares