(HTML/JS) Кнопка для создания отчета на основе JSON-ответа в базу данных не работает

Вопрос или проблема

Пожалуйста, я схожу с ума. В настоящее время я работаю над проектом базы данных с использованием PostGreSQL, Python Flask для бэкенда и HTML/CSS/Javascript для фронтенда. Но на одной из страниц, где должны быть две кнопки для создания отчетов, одна из них не работает, и при нажатии на нее появляется следующее сообщение об ошибке в “Просмотр кода”:

Uncaught (in promise) TypeError: Cannot read properties of null (reading ‘value’)
at fetchProdutoVendidoReport (script.js:50:61)
at HTMLButtonElement.onclick

И каждый раз, когда я пытаюсь это исправить, например, даю “id” элементам HTML формы, другая кнопка/запрос на той же странице не работает, и обе выдаёт 500: Internal Server Error.

Может кто-то помочь мне? Это тело HTML упомянутой страницы (я бразилец, поэтому многие вещи на португальском, но надеюсь, это не слишком сложно для понимания проблемы):

<body>

    <div id="header"></div>
    <script src="/frontend/components/header/header.js"></script>

    <h1>Gerar Relatórios</h1>

    <!-- Формуляр для отчета о заказе клиента -->
    <h2>Relatório de Pedido Cliente</h2>
    <form id="pedidoClienteForm">
        <label>Categoria: <input type="text" id="categoria" name="categoria"></label><br>
        <label>Data Mínima: <input type="date" id="startDate" name="data_min"></label><br>
        <label>Data Máxima: <input type="date" id="endDate" name="data_max"></label><br>
        <label>Fabricante: <input type="text" id="marca" name="fabricante"></label><br>
        <label>Método de Pagamento: <input type="text" id="metodoPagamento" name="metodo"></label><br>
        <label>Preço Mínimo: <input type="number" id="precoMin" name="preco_min"></label><br>
        <label>Preço Máximo: <input type="number" id="precoMax" name="preco_max"></label><br>
        <button type="button" onclick="fetchPedidoClienteReport()">Gerar Relatório de Pedido Cliente</button>
    </form>
    <div id="pedidoClienteResultado"></div>

    <h2>Resultados</h2>
    <table id="TabelaPedidoCliente">
        <thead>
            <tr>
                <th>Produto</th>
                <th>Categoria</th>
                <th>Marca</th>
                <th>Total Vendido</th>
                <th>Receita Total</th>
                <th>Método de Pagamento</th>
                <th>Data de Venda</th>
            </tr>
        </thead>
        <tbody></tbody>
    </table>

    <!-- Формуляр для отчета о проданном товаре -->
    <h2>Relatório de Produto Vendido</h2>
    <form id="produtoVendidoForm">
        <label>Data Mínima: <input type="date" id="DataComeco" name="data_min"></label><br>
        <label>Data Máxima: <input type="date" id="DataFinal" name="data_max"></label><br>
        <label>Preço Mínimo: <input type="number" id="preco_Min" name="preco_min"></label><br>
        <label>Preço Máximo: <input type="number" id="preco_Max" name="preco_max"></label><br>
        <button type="button" onclick="fetchProdutoVendidoReport()">Gerar Relatório de Produto Vendido</button>
    </form>
    <div id="produtoVendidoResultado"></div>

    <h2>Resultados</h2>
    <table id="TabelaProdutoVendido">
        <thead>
            <tr>
                <th>Produto</th>
                <th>Faixa de Preço</th>
                <th>Total Vendido</th>
                <th>Receita Total</th>
                <th>Método de Pagamento</th>
            </tr>
        </thead>
        <tbody></tbody>
    </table>

    <script src="/frontend/pages/relatorios/script.js"></script>
</body>

А это JS:

async function fetchPedidoClienteReport() {
        const startDate = document.getElementById('startDate').value;
        const endDate = document.getElementById('endDate').value;
        const categoria = document.getElementById('categoria').value;
        const marca = document.getElementById('marca').value;
        const precoMin = document.getElementById('precoMin').value;
        const precoMax = document.getElementById('precoMax').value;
        const metodoPagamento = document.getElementById('metodoPagamento').value;

        const url = `http://127.0.0.1:8000/relatorio/pedido_cliente?categoria=${categoria}&data_min=${startDate}&data_max=${endDate}&fabricante=${marca}&metodo=${metodoPagamento}&preco_min=${precoMin}&preco_max=${precoMax}`;
            try {
                // Отправляет запрос на бэкенд
                const response = await fetch(url, {
                    method: 'GET'
                });

                // Конвертирует ответ в JSON
                const data = await response.json();

                // Обновляет таблицу с данными
                    const tbody = document.getElementById('TabelaPedidoCliente').getElementsByTagName('tbody')[0];

                    // Очищает таблицу перед заполнением новыми данными
                    tbody.innerHTML = '';

                    function formataData(dateString) {
                        const date = new Date(dateString);
                        return date.toLocaleDateString('pt-BR'); // Формат 'DD/MM/YYYY'
                    }

                    // Заполняет таблицу данными отчета
                    data.forEach(item => {
                        const row = tbody.insertRow();

                    row.insertCell(0).textContent = item.nome;        // имя товара
                    row.insertCell(1).textContent = item.categoria;      // категория товара
                    row.insertCell(2).textContent = item.fabricante;     // производитель товара
                    row.insertCell(3).textContent = item.quantidade;  // всего продано
                    row.insertCell(4).textContent = item.total_venda;  // общая выручка
                    row.insertCell(5).textContent = item.metodo;         // метод оплаты
                    row.insertCell(6).textContent = formataData(item.data);     // дата продажи
                    })
            } catch (error) {
                console.error('Ошибка при генерации отчета:', error);
            }
    }

    // Функция для получения отчета о проданном товаре
    async function fetchProdutoVendidoReport() {
        const DataComeco = document.getElementById('DataComeco').value;
        const DataFinal = document.getElementById('DataFinal').value;
        const Preco_Min = document.getElementById('preco_Min').value;
        const Preco_Max = document.getElementById('preco_Max').value;

        const url = `http://127.0.0.1:8000/relatorio/produto_vendido?data_min=${DataComeco}&data_max=${DataFinal}&preco_min=${Preco_Min}&preco_max=${Preco_Max}`;
            try {
                // Отправляет запрос на бэкенд
                const response = await fetch(url, {
                    method: 'GET'
                });

                // Конвертирует ответ в JSON
                const data = await response.json();

                // Обновляет таблицу с данными
                    const tbody = document.getElementById('TabelaProdutoVendido').getElementsByTagName('tbody')[0];

                    // Очищает таблицу перед заполнением новыми данными
                    tbody.innerHTML = '';

                    // Заполняет таблицу данными отчета
                    data.forEach(item => {
                        const row = tbody.insertRow();

                    row.insertCell(0).textContent = item.nome;        // имя товара
                    row.insertCell(1).textContent = item.faixa_preco;      // категория товара
                    row.insertCell(2).textContent = item.total_vendido;     // производитель товара
                    row.insertCell(3).textContent = item.receita_total;  // всего продано
                    row.insertCell(4).textContent = item.metodo;         // метод оплаты
                    })
            } catch (error) {
                console.error('Ошибка при генерации отчета:', error);
            }
    }

Добавьте недостающие идентификаторы во втором формуляре.

<form id="produtoVendidoForm">
    <label>Data Mínima: <input type="date" id="DataComeco" name="data_min"></label><br>
    <label>Data Máxima: <input type="date" id="DataFinal" name="data_max"></label><br>
    <label>Preço Mínimo: <input type="number" id="preco_Min" name="preco_min"></label><br>
    <label>Preço Máximo: <input type="number" id="preco_Max" name="preco_max"></label><br>
    <button type="button" onclick="fetchProdutoVendidoReport()">Gerar Relatório de Produto Vendido</button>
</form>

Ответ или решение

Введение

В процессе разработки баз данных с использованием PostgreSQL и Flask, тревожные ситуации, как неработающие кнопки и ошибки сервера, могут озадачивать даже опытных разработчиков. Давайте разберем проблему с кнопкой "Gerar Relatório de Produto Vendido", которая вызывает ошибку при попытке получения отчета, и сколько различных факторов может влиять на это.

Проблема

Ошибка Uncaught (in promise) TypeError: Cannot read properties of null (reading 'value') говорит о том, что JavaScript не может найти элемент с указанным id. Это означает, что когда пользователь нажимает на кнопку, функция fetchProdutoVendidoReport пытается получить значение переменных, привязанных к элементам формы, которые не существуют.

Анализ HTML и JavaScript кода

Исходный HTML код для формы отчета о проданных товарах выглядит следующим образом:

<form id="produtoVendidoForm">
    <label>Data Mínima: <input type="date" name="data_min"></label><br>
    <label>Data Máxima: <input type="date" name="data_max"></label><br>
    <label>Preço Mínimo: <input type="number" name="preco_min"></label><br>
    <label>Preço Máximo: <input type="number" name="preco_max"></label><br>
    <button type="button" onclick="fetchProdutoVendidoReport()">Gerar Relatório de Produto Vendido</button>
</form>

Функция JavaScript, которая вызывает ошибку, содержит следующие строки:

const DataComeco = document.getElementById('DataComeco').value;
const DataFinal = document.getElementById('DataFinal').value;
const Preco_Min = document.getElementById('preco_Min').value;
const Preco_Max = document.getElementById('preco_Max').value;

Решение проблемы

Когда элементы формы не имеют уникальных идентификаторов (id), связанные с ними значения не могут быть извлечены, что приводит к вышеупомянутой ошибке. В вашей форме produtoVendidoForm отсутствуют id для полей ввода. Чтобы исправить это, добавьте недостающие id, как показано ниже:

<form id="produtoVendidoForm">
    <label>Data Mínima: <input type="date" id="DataComeco" name="data_min"></label><br>
    <label>Data Máxima: <input type="date" id="DataFinal" name="data_max"></label><br>
    <label>Preço Mínimo: <input type="number" id="preco_Min" name="preco_min"></label><br>
    <label>Preço Máximo: <input type="number" id="preco_Max" name="preco_max"></label><br>
    <button type="button" onclick="fetchProdutoVendidoReport()">Gerar Relatório de Produto Vendido</button>
</form>

Теперь функция fetchProdutoVendidoReport сможет корректно получать значения из формы.

Обработка Ошибок Серверной Часть

Ошибки 500 (Internal Server Error) чаще всего указывают на проблему на стороне сервера. Убедитесь в следующем:

  1. Корректные маршруты в Flask: Убедитесь, что URL, передаваемые в запросе, правильно настроены в вашем Flask приложении. Пример:

    @app.route('/relatorio/produto_vendido', methods=['GET'])
    def produto_vendido():
       # Ваш код обработки запроса
  2. Логи: Проверьте логи вашего приложения Flask для дополнительных подсказок о том, что именно вызывает ошибку сервера.

  3. Формат данных: Убедитесь, что данные, полученные на сервере, соответствуют предполагаемому формату.

Заключение

Сложности при разработке сложных веб-приложений могут вызывать стрессы, однако шаги, описанные в этой статье, помогут вам найти и устранить многие распространенные ошибки. Добавление недостающих id в форму должно устранить вашу первоначальную ошибку, тогда как проверка на стороне сервера поможет избежать 500 ошибок. Удачной разработки!

Оцените материал
Добавить комментарий

Капча загружается...