Вопрос или проблема
Не удается создать запись или просмотреть список записей в Кодовом журнале.
Я создаю журнал кода, чтобы записывать записи в виртуальный журнал и делать их доступными для просмотра, редактирования и удаления. Ошибка, которую я получаю, это:
main.js:71 Uncaught Error: No entries or entry list!
at toggleNoEntries (main.js:71:15)
at HTMLFormElement.\<anonymous\> (main.js:28:5) .
Может кто-то сказать, что я пропустил или сделал неправильно?
HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Журнал кода</title>
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/layout.css" />
<link rel="stylesheet" href="css/styles.css" />
</head>
<body>
<header>
<div class="container">
<div class="row">
<div class="column-full navbar">
<h1 class="code-journal">Журнал кода</h1>
<div>
<a href="#" id="entries-link">Записи</a>
</div>
</div>
</div>
</div>
</header>
<main class="container">
<div data-view="entry-form">
<div class="row">
<div class="column-full">
<h1 class="new-entry">Новая запись</h1>
</div>
</div>
<form id="entry-form">
<div class="row">
<div class="column-half">
<img
id="url-preview"
src="/images/placeholder-image-square.jpg"
alt="Предпросмотр изображения"
class="url-preview" />
</div>
<div class="column-half">
<div class="input">
<label for="title">Название</label>
<input type="text" id="title" required />
</div>
<div class="input">
<label for="photo-url">URL изображения</label>
<input type="url" id="photo-url" required />
</div>
</div>
</div>
<div class="row">
<div class="column-full">
<label for="content">Заметки</label>
<textarea id="content" cols="30" rows="10" required></textarea>
</div>
</div>
<div class="row">
<div class="column-full button-container">
<button type="submit">СОХРАНИТЬ</button>
</div>
</div>
</form>
</div>
<div data-view="entries" class="hidden">
<div class="row">
<div class="column-full entries-heading">
<h1>Записи</h1>
<p class="no-entries">Нет записей</p>
<a href="#" id="new-entry-button" class="new-entry-button">НОВАЯ</a>
</div>
</div>
<ul class="entry-list"></ul>
</div>
</main>
<script src="js/data.js"></script>
<script src="js/main.js"></script>
</body>
</html>
Typescript:
const $form = document.querySelector('#entry-form') as HTMLFormElement;
const $urlPreview = document.querySelector('#url-preview') as HTMLImageElement;
const $photoUrlInput = document.querySelector('#photo-url') as HTMLInputElement;
if (!$form) throw new Error('$form запрос не удался!');
if (!$urlPreview) throw new Error('$urlPreview запрос не удался!');
if (!$photoUrlInput) throw new Error('$photoUrlInput запрос не удался!');
$photoUrlInput.addEventListener('input', function (event: Event) {
const target = event.target as HTMLInputElement;
$urlPreview.src = target.value || "https://stackoverflow.com/questions/79009095/images/placeholder-image-square.jpg";
});
$form.addEventListener('submit', function (event: Event) {
event.preventDefault();
const newEntry = {
entryId: data.nextEntryId,
title: ($form.elements.namedItem('title') as HTMLInputElement).value,
photoUrl: $photoUrlInput.value,
content: ($form.elements.namedItem('content') as HTMLTextAreaElement).value,
};
const $newEntryElement = renderEntry(newEntry);
const $entryList = document.getElementById('entry-list');
if ($entryList && $newEntryElement) {
$entryList.appendChild($newEntryElement);
}
toggleNoEntries();
data.nextEntryId++;
data.entries.unshift(newEntry);
writeData();
$form.reset();
$urlPreview.src="https://stackoverflow.com/questions/79009095/images/placeholder-image-square.jpg";
});
function renderEntry(entry: JournalEntry): HTMLElement {
const $li = document.createElement('li');
$li.classList.add('row');
const $imgWrapper = document.createElement('div');
$imgWrapper.classList.add('column-half');
const $img = document.createElement('img');
$img.src = entry.photoUrl;
$img.alt = `${entry.title}`;
$img.classList.add('url-preview');
const $div = document.createElement('div');
$div.classList.add('column-half');
const $h2 = document.createElement('h2');
$h2.textContent = entry.title;
const $p = document.createElement('p');
$p.textContent = entry.content;
$li.appendChild($imgWrapper);
$li.appendChild($div);
$div.appendChild($h2);
$div.appendChild($p);
return $li;
}
document.addEventListener('DOMContentLoaded', function () {
const $ul = document.querySelector('ul');
if (!$ul) throw new Error('$ul запрос не удался!');
data.entries.forEach((entry) => {
const entryElement = renderEntry(entry);
$ul.appendChild(entryElement);
});
});
function toggleNoEntries(): void {
const $noEntries = document.getElementById(
'no-entries',
) as HTMLParagraphElement;
// const $entryList = document.getElementById('.entry-list');
if (!$noEntries) throw new Error('Нет записей!');
if (data.entries.length === 0) {
$noEntries.style.display = 'block';
} else {
$noEntries.style.display = 'none';
}
}
function viewSwap(view: 'entries' | 'entry-form'): void {
const $entriesView = document.querySelector(
'[data-view="entries"]',
) as HTMLElement;
const $entryFormView = document.querySelector(
'[data-view="entry-form"]',
) as HTMLElement;
if (!$entriesView || !$entryFormView)
throw new Error('Элементы вида не найдены!');
if (view === 'entries') {
$entriesView.classList.remove('hidden');
$entryFormView.classList.add('hidden');
} else if (view === 'entry-form') {
$entryFormView.classList.remove('hidden');
$entriesView.classList.add('hidden');
}
data.view = view;
}
const $entriesLink = document.getElementById(
'entries-link',
) as HTMLAnchorElement;
if (!$entriesLink) throw new Error('$entriesLink запрос не удался!');
$entriesLink.addEventListener('click', function (event: Event) {
event.preventDefault();
viewSwap('entries');
});
const $newEntryButton = document.getElementById(
'new-entry-button',
) as HTMLAnchorElement;
if (!$newEntryButton) throw new Error('$newEntryButton запрос не удался!');
$newEntryButton.addEventListener('click', function (event: Event) {
event.preventDefault();
viewSwap('entry-form');
});
Мне не нужен $entryList, но если я его удалю, я потеряю содержимое заголовка и заметок, когда нажимаю кнопку записей в заголовке. Может быть, это тоже что-то неправильное в моем html?
Ответ или решение
Проблема, с которой вы столкнулись, обусловлена тем, что в коде отсутствует правильная идентификация элемента списка записей, а также может быть неправильное обращение к некоторым элементам в функции toggleNoEntries
. Рассмотрим это более подробно.
Ошибка
Исходя из текста ошибки:
Uncaught Error: No entries or entry list!
эта ошибка возникает в функции toggleNoEntries
, когда код пытается получить доступ к элементу, который, скорее всего, не существует.
Решение
-
Проверьте идентификаторы HTML-элементов: Убедитесь, что элементы с идентификатором
entry-list
иno-entries
действительно существуют в разметке HTML. В вашем HTML-коде элемент с классомno-entries
имеет следующий код:<p class="no-entries">No entries</p>
Однако, вы обращаетесь к элементу с ID
no-entries
в коде JavaScript. Измените его на класс:const $noEntries = document.querySelector('.no-entries') as HTMLParagraphElement;
-
Исправление выборки элементов: Попробуйте обновить выборку для
entry-list
:const $entryList = document.querySelector('.entry-list') as HTMLUListElement;
-
Обновление функции
toggleNoEntries
: Убедитесь, что ваша функцияtoggleNoEntries
корректно работает с элементомno-entries
(илиnoEntries
):function toggleNoEntries(): void { const $noEntries = document.querySelector('.no-entries') as HTMLParagraphElement; const $entryList = document.querySelector('.entry-list') as HTMLUListElement; if (!$noEntries) throw new Error('No entries paragraph not found!'); if (data.entries.length === 0) { $noEntries.style.display = 'block'; $entryList.style.display = 'none'; // Скрыть список записей } else { $noEntries.style.display = 'none'; $entryList.style.display = 'block'; // Показать список записей } }
-
Проверка данных: Убедитесь, что объект
data
правильно инициализирован, иdata.entries
существует. Это может быть начальным значением, например:const data = { entries: [], nextEntryId: 1, view: 'entry-form', };
- Обработка событий: Добавьте вызов
toggleNoEntries()
в нужные места, чтобы он обновлялся каждый раз, когда вы добавляете новую запись или переключаетесь между видами.
Полный пример
Для лучшего понимания, вот исправленная версия вашей функции toggleNoEntries
и добавленный код для получения элемента списка:
function toggleNoEntries(): void {
const $noEntries = document.querySelector('.no-entries') as HTMLParagraphElement;
const $entryList = document.querySelector('.entry-list') as HTMLUListElement;
if (!$noEntries || !$entryList) throw new Error('Required elements not found!');
if (data.entries.length === 0) {
$noEntries.style.display = 'block';
$entryList.style.display = 'none';
} else {
$noEntries.style.display = 'none';
$entryList.style.display = 'block';
}
}
Эти шаги должны помочь вам устранить проблему и успешно работать с вашим виртуальным журналом записей. Убедитесь, что все идентификаторы и классы соответствуют объявленным в HTML-коде, а также проверяйте наличие доступных элементов перед их использованием в JavaScript.