AJAX & Snippets
Na era dos aplicativos modernos da Web, em que a funcionalidade geralmente se estende entre o servidor e o navegador, o AJAX é um elemento de conexão essencial. Que opções o Nette Framework oferece nessa área?
- envio de partes do modelo, os chamados snippets
- passagem de variáveis entre PHP e JavaScript
- ferramentas para depuração de solicitações AJAX
Solicitação de AJAX
Basicamente, uma solicitação AJAX não difere de uma solicitação HTTP clássica. Um apresentador é chamado com parâmetros específicos. Cabe ao apresentador decidir como responder à solicitação: ele pode retornar dados no formato JSON, enviar uma parte do código HTML, um documento XML etc.
No lado do navegador, iniciamos uma solicitação AJAX usando a função fetch()
:
No lado do servidor, uma solicitação AJAX é reconhecida pelo método $httpRequest->isAjax()
do serviço que encapsula a solicitação HTTP. Ele usa o cabeçalho HTTP X-Requested-With
, portanto, é
essencial enviá-lo. No apresentador, você pode usar o método $this->isAjax()
.
Se você quiser enviar dados no formato JSON, use o método sendJson()
método. O método também encerra a atividade do
apresentador.
Se você planeja responder com um modelo especial projetado para AJAX, pode fazer isso da seguinte forma:
Trechos
A ferramenta mais poderosa oferecida pela Nette para conectar o servidor com o cliente são os snippets. Com eles, você pode transformar um aplicativo comum em um aplicativo AJAX com o mínimo de esforço e algumas linhas de código. O exemplo Fifteen demonstra como tudo isso funciona, e seu código pode ser encontrado no GitHub.
Os snippets, ou recortes, permitem que você atualize apenas partes da página, em vez de recarregar a página inteira. Isso é mais rápido e mais eficiente, além de proporcionar uma experiência de usuário mais confortável. Os snippets podem lembrá-lo do Hotwire para Ruby on Rails ou do Symfony UX Turbo. É interessante notar que a Nette introduziu os snippets 14 anos antes.
Como os snippets funcionam? Quando a página é carregada pela primeira vez (uma solicitação não AJAX), a página inteira, incluindo todos os snippets, é carregada. Quando o usuário interage com a página (por exemplo, clica em um botão, envia um formulário etc.), em vez de carregar a página inteira, é feita uma solicitação AJAX. O código no apresentador executa a ação e decide quais trechos precisam ser atualizados. A Nette renderiza esses trechos e os envia na forma de uma matriz JSON. O código de manipulação no navegador insere os trechos recebidos de volta na página. Portanto, somente o código dos trechos alterados é transferido, economizando largura de banda e acelerando o carregamento em comparação com a transferência de todo o conteúdo da página.
Naja
Para lidar com snippets no navegador, é usada a biblioteca Naja. Instale-a como um pacote node.js (para uso com aplicativos como Webpack, Rollup, Vite, Parcel e outros):
… ou insira-a diretamente no modelo da página:
Primeiro, você precisa inicializar a biblioteca:
Para transformar um link comum (sinal) ou o envio de um formulário em uma solicitação AJAX, basta marcar o respectivo
link, formulário ou botão com a classe ajax
:
Redesenho de snippets
Todos os objetos da classe Control (inclusive o próprio Presenter) mantêm um registro da
ocorrência de alterações que exijam o redesenho. O método redrawControl()
é usado para essa finalidade.
O Nette também permite um controle mais preciso do que precisa ser redesenhado. O método mencionado acima pode usar o nome do snippet como argumento. Assim, é possível invalidar (ou seja, forçar um redesenho) no nível da parte do modelo. Se o componente inteiro for invalidado, todos os trechos dele também serão redesenhados:
Snippets em Latte
Usar snippets no Latte é extremamente fácil. Para definir uma parte do modelo como um snippet, basta envolvê-la nas tags
{snippet}
e {/snippet}
:
O snippet cria um elemento <div>
na página HTML com um id
especialmente gerado. Ao redesenhar
um snippet, o conteúdo desse elemento é atualizado. Portanto, quando a página é renderizada inicialmente, todos os snippets
também devem ser renderizados, mesmo que inicialmente estejam vazios.
Você também pode criar um snippet com um elemento diferente de <div>
usando um atributo n::
Áreas de snippet
Os nomes dos snippets também podem ser expressões:
Dessa forma, obteremos vários snippets como item-0
, item-1
, etc. Se invalidássemos diretamente um
snippet dinâmico (por exemplo, item-1
), nada seria redesenhado. O motivo é que os snippets funcionam como
verdadeiros trechos e somente eles são renderizados diretamente. Entretanto, no modelo, não há tecnicamente um trecho chamado
item-1
. Ele só aparece quando se executa o código ao redor do snippet, nesse caso, o loop foreach. Por isso,
marcaremos a parte do modelo que precisa ser executada com a tag {snippetArea}
:
E redesenharemos tanto o snippet individual quanto toda a área abrangente:
Também é essencial garantir que a matriz $items
contenha apenas os itens que devem ser redesenhados.
Ao inserir outro modelo no modelo principal usando a tag {include}
, que tem snippets, é necessário envolver
novamente o modelo incluído em um snippetArea
e invalidar o snippet e a área juntos:
Snippets em componentes
Você pode criar snippets em componentes, e o Nette os redesenha automaticamente. Entretanto, há
uma limitação específica: para redesenhar os snippets, ele chama o método render()
sem nenhum parâmetro.
Portanto, a passagem de parâmetros no modelo não funcionará:
Envio de dados do usuário
Juntamente com os snippets, você pode enviar quaisquer dados adicionais ao cliente. Basta gravá-los no objeto
payload
:
Parâmetros de envio
Quando enviamos parâmetros ao componente por meio de solicitação AJAX, sejam eles parâmetros de sinal ou parâmetros
persistentes, devemos fornecer seu nome global, que também contém o nome do componente. O nome completo do parâmetro retorna
o método getParameterId()
.
Um método handle com os parâmetros correspondentes no componente: