Como criar uma interface simples em AJAX usando Views

Oi pessoal! É bem provável que em algum determinado momento, aparecerá aquele cliente pedindo pra gente fazer uma lista de links ou um tipo de menu que carregará o conteúdo sem atualização de página, ou seja, via AJAX. Assim, vamos fazer um esquema aqui bem fácil, listando os títulos dos conteúdos na lateral esquerda e carregando o conteúdo completo ao lado direito, na região principal de conteúdo. O exemplo que vou citar serve de base para fazer coisas do tipo.

A configuração

Primeira coisa é criar uma página básica, do tipo "Basic Page". Essa página vai servir como a nossa interface AJAX. A única coisa que essa página vai conter é um pouco de HTML, que vai empacotar os nodes que serão inseridos:

<div id="mymodule-ajax-wrapper">
  <p>Clique em um título no lado esquerdo para ver o conteúdo!</p>
</div>

Nós também vamos fazer uma view simples, do tipo conteúdo, com display "block", filtrando por conteúdos do tipo "Artigo".

 

Trabalhando com Views

Primeiro, vamos configurar a view para que use o modo AJAX.

Mesmo que não exista um pager ou qualquer outra coisa que possa ser manipulado via AJAX na view, ao ligar o modo "Use AJAX" a view irá incluir o Javascrip AJAX na página. Também existem outras formas para fazer isso, mas desse jeito é bem conveniente.

Em seguida, vamos incluir o ID do node como um campo em nossa view. O nid não precisa ser ser exibido para o usuário final, mas nós precisamos desse dado para que possamos passá-lo junto com a requisição AJAX. Dessa forma, vamos marcar também a opção "Excluir da exibição" nesse campo.

Os campos da view devem ser organizados de forma que o nid fique acima do título do node. Mesmo que o nid não seja visível, precisa vir antes do título para que possamos usá-lo dentro das configuração do campo de título, conforme veremos aqui.

Depois é preciso ajustar a exibição do título nas configurações do campo na view. Desmarque a opção "Linkar este campo para o conteúdo original". Ao invés de usar o link padrão, vamos abrir as opções "Reescrever resultados" e marcar a opção "Exibir este campo como link". Aqui vamos configurar para que o caminho do link seja um caminho de retorno da chamada personalizada em AJAX. Assim, vamos colocar algo como "mymodule-ajax/nojs/[nid]", onde "[nid]" é o valor do token fornecido pelo campo ID do node, usado para que o retorno reconheça qual o node está sendo chamado. Existe mais uma coisa que devemos notar nessa url. O Drupal irá mudar automaticamente a parte "nojs" do link através do "ajax" se o navegador estiver com JavaScript habilitado. Podemos detectar isso mais tarde no lado do servidor para ter certeza que o nosso AJAX trabalha bem para quem está sem o JS habilitado.

Observe também que adicionamos a classe "use-ajax" no link. Isso é importante para informar ao javascript ajax do Drupal que esse link deve ser ajax.

Salve a view e teste-a. Se tudo estiver certo, a gente pode ver de clicar em um link dentro do bloco que lista os títulos dos nodes, ver o throbber do ajax por algum instante e depois receber uma mensagem de erro feia em um alerta. Esse é um erro 404, pois ainda não existe código escrito no lado do servidor, ainda.

Módulo customizado

Vamos fazer um módulo simples para que escute as requisições de página de acordo os caminhos que definimos para os nossos links nos títulos de conteúdos na view (mymodule-ajax/nojs/[nid]) e retornar os comandos ajax para exibir o node solicitado pelo nid. Já falei aqui antes sobre como criar um módulo.

Precisamos de duas funções aqui. A primeira é a implementação do hook_menu(), que ira registrar o retorno ajax na url mymodule-ajax/nojs/[nid].

function mymodule_menu() {
  $items['mymodule-ajax/%/%node'] = array(
    'access arguments' => array('access content'),
    'page callback' => 'mymodule_ajax_callback',
    'page arguments' => array(1,2),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

A chave para os itens de menu no array é o caminho de resposta para a nossa chamada ajax: "mymodule-ajax/%/%node". O primeiro de porcentagem é a primeira variável no caminho. Este processo pode ser nojs ou ajax, dependendo se o usuário tem JS habilitado no navegador ou não. A segunda variável, %node, é a ID do node que será automaticamente passada pela função node_load() e dar a chamada de retorno como um objeto $node completo. Depois que temos o hook_menu(), tudo o que precisamos fazer é escrever uma chamada simples de ajax, mymodule_ajax_callback().

function mymodule_ajax_callback($js, $node) {
  // If the nojs didn't get changed to ajax, the user has no javascript.
  // Send them to the regular node page instead.
  if ($js == 'nojs') {
    drupal_goto('node/' . $node->nid);
  }

  // Get the render array for the node.
  $build = node_view($node);

  // Render the node into html.
  $html = render($build);

  // Prepare an ajax command to insert the node html into our ajax wrapper.
  $commands = array();
  $commands[] = ajax_command_html('#mymodule-ajax-wrapper', $html);

  // Render the commands into JSON and print them.
  print ajax_render($commands);
  exit;  // Exit so Drupal doesn't have a chance to build a whole page.
}

Leva apenas algumas linhas de PHP para fazer a interface AJAX funcionar. Primeiro, verificamos para ver se o "pedaço" da url requisitada continua como "nojs". Se for, isso significa que o usuário não está com JS habilitado no navegador. Para manter a acessibilidade, nós redirecionamos este usuário para a página do node normalmente. Para os usuários que têm JS habilitado no navegador, convertemos o node em HTML usando node_view() e drupal_render(). Por fim, usamos comandos AJAX embutidos no Drupal para inserir o nosso node dentro da div html "#mymodule-ajax-wrapper", que montamos no início. A função ajax_command_html() simplesmente invoca o jQuery .html() para a inserção de conteúdo dentro do invólucro selecionado. Quando terminarmos a construção do array de comandos ajax, nós simplesmente os transformamos em JSON usando ajax_render() e os imprimimos na página.

É isso! Habilite o módulo, limpe o cache e navegue um pouco. A API AJAX do Drupal é sensacional! Não precisamos escrever nenhum JavaScript, somente PHP. :)

Este post é uma tradução livre adaptada do Mike Kadin.