Atualizado: 07/12/2024

Carregando HTML com XMLHttpRequest - JavaScript

Frequentemente, em um código de página, é necessário obter algum código HTML do servidor. Por exemplo, uma página pode ser um site de uma única página que carrega o código HTML necessário através de uma solicitação AJAX e o insere na página. Portanto, vamos examinar como carregar código HTML via AJAX.

Para o servidor, assim como no tema anterior, usaremos Node.js como a opção mais simples, mas, naturalmente, qualquer outra tecnologia de servidor ou servidor web pode ser usada.

Então, vamos definir uma pasta no disco rígido para o projeto, onde criaremos três arquivos:

  • index.html: a página principal da aplicação

  • home.html: a página com o código HTML que carregaremos via AJAX

  • server.js: o arquivo da aplicação de servidor que usará Node.js

Definindo o Servidor

O arquivo server.js conterá o código do servidor Node.js. Definiremos o seguinte código:

const http = require("http");
const fs = require("fs");
      
http.createServer((request, response) => {
    // Obtendo o caminho após a barra, a barra é o primeiro caractere no caminho
    let filePath = request.url.substring(1);
    // Se o caminho estiver vazio, enviamos a página principal index.html
    if (!filePath) filePath = "index.html";  
    // Definimos o tipo de resposta como HTML
    response.setHeader("Content-Type", "text/html; charset=utf-8;");
    fs.readFile(filePath, (error, data) => {
        if (error) {  // Em caso de erro
            response.statusCode = 404;
            response.end("

Recurso não encontrado!

"); } else { response.end(data); } }); }).listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));

Vamos examinar o código em detalhes. Primeiro, são importados os pacotes com funcionalidades que utilizaremos:

const http = require("http");   // Para lidar com solicitações recebidas
const fs = require("fs");       // Para ler arquivos do disco rígido

Para criar o servidor, usamos a função http.createServer(). Esta função recebe uma função de callback que é chamada toda vez que o servidor recebe uma solicitação. Esta função possui dois parâmetros: request (contém os dados da solicitação) e response (controla o envio da resposta).

Na função de callback, podemos obter o caminho do recurso solicitado através da propriedade request.url. Precisamos lidar com solicitações para as páginas "index.html" e "home.html" (e, no futuro, para outras páginas HTML). O caminho sempre começa com uma barra "/". Por exemplo, uma solicitação para a página "home.html" terá o caminho "/home.html". Portanto, para obter o caminho dos arquivos no disco rígido, precisamos remover a barra inicial:

let filePath = request.url.substring(1);

No entanto, se a solicitação for para a raiz do site, o caminho consistirá apenas de uma barra - "/". Nesse caso, se removermos essa barra, teremos uma string vazia. Portanto, se a solicitação for para a raiz da aplicação web, consideraremos que a solicitação é para a página principal - index.html:

if (!filePath) filePath = "index.html";

Como a resposta do servidor será código HTML, usamos o método setHeader() para definir o valor "text/html" para o cabeçalho "Content-Type":

response.setHeader("Content-Type", "text/html; charset=utf-8;");

Em seguida, usamos a função fs.readFile para ler o arquivo solicitado. O primeiro parâmetro da função é o caminho do arquivo (presumimos que o arquivo esteja na mesma pasta que o arquivo do servidor server.js). O segundo parâmetro é uma função de callback que é chamada após a leitura do arquivo e recebe seu conteúdo como segundo parâmetro, data. Se o arquivo solicitado não existir, enviamos um erro 404:

fs.readFile(filePath, (error, data) => {
  if (error) {  // Em caso de erro
      response.statusCode = 404;
      response.end("

Recurso não encontrado!

"); } else { response.end(data); } });

Por fim, usamos a função listen() para iniciar o servidor web na porta 3000. Ou seja, o servidor será iniciado no endereço http://localhost:3000.

}).listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));

Definindo o Código HTML para Carregamento

O arquivo home.html conterá um código simples que será carregado pela página web. O código será o seguinte:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Home Page</title>
</head>
<body>
    <h1>Home Page</h1>
    <p>Home Page Text</p>
</body>
</html>

Definindo a Página Principal e Carregando Dados

Agora, definiremos o código da página principal index.html, que carregará a página home.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Programício</title>
</head>
<body>
<script>
const xhr = new XMLHttpRequest();
xhr.onload = () => {  // Handler para receber a resposta do servidor
    if (xhr.status == 200) {  // Se o código de resposta for 200
        const html = xhr.responseText;  // Obtemos a resposta
        console.log(html);  // Exibimos a resposta no console do navegador
    } else {  // Caso contrário, exibimos o status da resposta
        console.log("Resposta do servidor: ", xhr.statusText);
    }
};
xhr.open("GET", "/home.html");  // Solicitação GET para o recurso /home.html
xhr.setRequestHeader("Accept", "text/html");  // Aceitamos apenas HTML
xhr.send();  // Enviamos a solicitação
</script>
</body>
</html>

No handler de carregamento xhr.onload, obtemos o texto da resposta através de xhr.responseText e exibimos a resposta no console.

Agora, no console, navegue até a pasta do servidor usando o comando cd e inicie o servidor com o comando node server.js:

C:\app>node server.js
Servidor iniciado em http://localhost:3000

Após iniciar o servidor, podemos acessar o endereço http://localhost:3000 no navegador. A página exibida conterá um código JavaScript que fará uma solicitação à página home.html. O código JavaScript obterá essa página e exibirá seu conteúdo no console:

Obtendo Código HTML em Requisição AJAX com XMLHttpRequest em JavaScript

Gerenciando o Conteúdo HTML

No exemplo anterior, obtivemos o conteúdo da página como texto simples. No entanto, como esse texto contém marcação HTML, podemos carregá-lo na página web. Assim, vamos modificar o código da página index.html da seguinte forma:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Programício</title>
</head>
<body>
<div id="content"></div>
<script>
const contentDiv = document.getElementById("content");  // Elemento para carregar HTML
const xhr = new XMLHttpRequest();
  
xhr.onload = () => { 
    if (xhr.status == 200) {
        contentDiv.innerHTML = xhr.responseText;  // Exibimos a resposta recebida em contentDiv
    } else {  // Caso contrário, exibimos o texto do status
        console.log("Resposta do servidor: ", xhr.statusText);
    }
};
xhr.open("GET", "/home.html");  // Solicitação GET para o recurso /home.html
xhr.setRequestHeader("Accept", "text/html");  // Aceitamos apenas HTML
xhr.send();  // Enviamos a solicitação
</script>
</body>
</html>

Neste caso, carregamos o código da página home.html no elemento com id="content":

Carregando Código HTML em Página Web em Requisição AJAX com XMLHttpRequest em JavaScript

No entanto, o problema aqui é que o código da página home.html contém elementos head, title e metadados com a tag <meta />. Não faz sentido carregar esses elementos em outra página web. Além disso, podemos querer carregar apenas um elemento específico da página home.html, e não todo o seu código. Nesse caso, podemos obter a resposta através da propriedade responseXML e, em seguida, manipulá-la como um documento HTML padrão. Por exemplo, vamos modificar o código JavaScript da seguinte forma:

const contentDiv = document.getElementById("content");
 
const xhr = new XMLHttpRequest();
xhr.onload = () => {  // Handler para receber a resposta do servidor
    if (xhr.status == 200) {
        // Carregamos apenas o conteúdo do elemento body
        contentDiv.innerHTML = xhr.responseXML.body.innerHTML;
    } else {
        console.log("Resposta do servidor: ", xhr.statusText);
    }
};
xhr.open("GET", "/home.html");  // Solicitação GET para o recurso /home.html
xhr.responseType = "document";  // Definimos o tipo de resposta
xhr.setRequestHeader("Accept", "text/html");  // Aceitamos apenas HTML
xhr.send();  // Enviamos a solicitação

Aqui, é importante observar dois pontos. Primeiro, definimos o tipo de resposta como "document":

xhr.responseType = "document";

Isso nos permite obter a resposta como um objeto do tipo Document, semelhante à propriedade document em uma página web.

Para obter a resposta em formato HTML/XML, usamos a propriedade responseXML. Como essa propriedade representa um objeto Document, utilizamos a propriedade body para acessar o conteúdo da página diretamente:

contentDiv.innerHTML = xhr.responseXML.body.innerHTML;

Como resultado, o conteúdo do elemento body da página home.html será carregado em contentDiv.

Da mesma forma, podemos acessar outras propriedades do objeto Document. Por exemplo, para obter o título da página:

document.title = xhr.responseXML.title;

Ou para carregar na página apenas o texto do título <h1>:

contentDiv.innerHTML = xhr.responseXML.querySelector("h1").textContent;

Carregamento Dinâmico de Componentes

A capacidade de carregar código HTML e inseri-lo na página nos permite ir além e dividir a funcionalidade da aplicação em vários componentes, carregando-os conforme necessário. Por exemplo, vamos supor que no projeto temos os seguintes arquivos:

  • server.js: arquivo da aplicação do servidor em Node.js

  • index.html: página principal da aplicação

  • home.html: arquivo do componente home

  • about.html: arquivo do componente about

  • contact.html: arquivo do componente contact

O arquivo da aplicação do servidor em Node.js, server.js, permanece o mesmo definido anteriormente neste tema.

O arquivo home.html contém um código simples como o seguinte:

<h1>Home Page</h1>
<p>Home Page Text</p>

O arquivo about.html tem uma estrutura similar:

<h1>About Page</h1>
<p>About Page Text</p>

E o código do arquivo contact.html:

<h1>Contact Page</h1>
<p>Contact Page Text</p>

Esses arquivos representam componentes que serão carregados na página principal.

Na página principal index.html, definimos o seguinte código:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Programício</title>
</head>
<body>
<nav>
    <a href="home">Home</a> | 
    <a href="about">About</a> | 
    <a href="contact">Contact</a>
</nav>
<div id="content"></div>
<script>
const contentDiv = document.getElementById("content");

function loadContent(fileName) {
    const xhr = new XMLHttpRequest();
    xhr.onload = () => {
        if (xhr.status == 200) {
            contentDiv.innerHTML = xhr.responseText;
            document.title = fileName;
        } else {
            console.log("Resposta do servidor: ", xhr.statusText);
        }
    };
    xhr.open("GET", fileName + ".html");
    xhr.setRequestHeader("Accept", "text/html");
    xhr.send();
}

// Configura o handler de clique para os links
const links = document.getElementsByTagName("a"); 
for (let i = 0; i < links.length; i++) {
    links[i].addEventListener("click", (e) => {
        loadContent(links[i].getAttribute("href"));
        e.preventDefault();
    });
}

// Carrega o componente home por padrão
loadContent("home");
</script>
</body>
</html>

Aqui, para a navegação entre os componentes, colocamos uma série de links na página:

<nav>
  <a href="home">Home</a> | 
  <a href="about">About</a> | 
  <a href="contact">Contact</a>
</nav>

O endereço de cada link coincide com o nome da página do componente correspondente, sem a extensão ".html".

Cada um dos componentes será carregado na página dentro do elemento com id="content", obtido no código JavaScript na constante contentDiv:

const contentDiv = document.getElementById("content");

No código JavaScript, configuramos um handler para cada link, onde chamamos a função loadContent e passamos o valor do atributo href do link, que é o endereço do componente:

const links = document.getElementsByTagName("a"); 
for (let i = 0; i < links.length; i++) {
    links[i].addEventListener("click", (e) => {
        loadContent(links[i].getAttribute("href"));
        e.preventDefault();
    });
}

Na função loadContent, usamos o endereço do link para enviar uma solicitação AJAX, e a resposta (o HTML recebido) é carregada no elemento contentDiv:

contentDiv.innerHTML = xhr.responseText;

Ao carregar a página, carregamos imediatamente o código do componente home como o componente padrão:

loadContent("home");

Dessa forma, na página principal, podemos acessar componentes específicos clicando nos links:

Carregamento Dinâmico de Componentes na Página Web com Solicitação AJAX usando XMLHttpRequest em JavaScript. Página Home.
Carregamento Dinâmico de Componentes na Página Web com Solicitação AJAX usando XMLHttpRequest em JavaScript. Página About.
Carregamento Dinâmico de Componentes na Página Web com Solicitação AJAX usando XMLHttpRequest em JavaScript. Página Contact.
Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com