В настоящее время я работаю над списком дел из проекта Odin. Согласно инструкциям, мой список задач может создать новый проект, в который мы затем сможем добавлять задачи. Теперь у меня есть боковая панель со списком всех существующих проектов, и когда я нажимаю на любой из проектов, детали проекта отображаются в основной части. прилагаю скриншоты страницы
прежде чем я нажму на проект
после того, как я нажму на проект
В настоящее время у меня возникли проблемы с попыткой добавить новые задачи в проект, который активен в основной части, поскольку я не могу получить его индекс.
В моем модуле addTaskModal.js я создал всплывающее диалоговое окно, позволяющее пользователям вводить сведения о задачах, которые необходимо добавить в активный проект. Но я застрял на несколько часов и не могу понять, как получить индекс проекта, отображаемый на главной странице.
Вот мой код, который отображает проект в теле:
import {
addTaskModal
} from './addTaskModal.js';
import {
myProjects
} from './myProjects.js';
const mainContent = document.querySelector('#main');
export default function renderMain(event) { //render project from sidebar to mainContent body
mainContent.textContent = '';
mainContent.appendChild(addTaskModal); //dialog to input new task and its priority
let index = parseInt(event.target.id.split('-')[1]);
const projectCard = document.createElement('div');
projectCard.classList.add('card');
const projectCardHeader = document.createElement('h3');
projectCardHeader.classList.add('cardheader');
projectCardHeader.textContent = myProjects[index].name
projectCard.appendChild(projectCardHeader);
const projectDue = document.createElement('div');
projectDue.textContent = myProjects[index].due;
projectDue.classList.add('date');
projectCard.appendChild(projectDue);
for (let i = 0; i < myProjects[index].tasks?.length; i++) {
const tasks = document.createElement('div');
const deleteBtn = document.createElement('button');
deleteBtn.textContent = 'Delete Task';
deleteBtn.addEventListener('click', () => {
myProjects[index].tasks.splice(i, 1);
localStorage.setItem('projects', JSON.stringify(myProjects));
renderMain(event);
})
//when we want to update after delete, just store with same "key" and the "key" will be updated.
tasks.textContent = myProjects[index].tasks[i].name;
tasks.classList.add('tasks');
tasks.appendChild(deleteBtn);
projectCard.appendChild(tasks);
}
const addTaskBtn = document.createElement('button');
addTaskBtn.textContent = "Add Task";
mainContent.appendChild(addTaskBtn);
addTaskBtn.addEventListener('click', () => {
addTaskModal.showModal();
});
mainContent.appendChild(addTaskBtn);
mainContent.appendChild(projectCard)
}
Вот код массива myProjects для контекста:
let myProjects = JSON.parse(localStorage.getItem('projects')) || [{
name: "Go to supermarket",
due: "12/2/25",
tasks: [{
name: "Buy apples",
priority: "high"
},
{
name: "Buy Eggs",
priority: "medium"
}
]
},
{
name: "Clean the house",
due: "13/2/25",
tasks: [{
name: "Sweep and mop the floor",
priority: "high"
},
{
name: "Do laundry",
priority: "high"
}
]
}
];
export {
myProjects
};
Вот addTaskModal.js для создания всплывающего диалогового окна, в котором пользователи могут ввести сведения о новой задаче.
import { myProjects } from "./myProjects";
const addTaskModal = document.createElement('dialog');
addTaskModal.classList.add('modal');
//const addTaskModal = document.createElement('div');
//addTaskModal.classList.add('hidden');
//create label and input box for user to input new task title
const newTask = document.createElement('div');
newTask.classList.add('modallabel');
newTask.textContent = "New Task :";
const newTaskInput = document.createElement('input');
newTaskInput.setAttribute('placeholder', 'Add New Task Here');
newTaskInput.setAttribute('id', 'newtaskinput');
newTaskInput.classList.add('inputbox');
newTask.appendChild(newTaskInput);
//create label and select input for user to input new task priority
const newPriority = document.createElement('div');
newPriority.textContent = "Priority: ";
newPriority.classList.add('prioritylabel');
const newPriorityInput = document.createElement('select');
newPriorityInput.setAttribute('id', 'newpriorityinput');
//add options to select
const selectHigh = document.createElement('option');
selectHigh.textContent = "High";
selectHigh.setAttribute('value', 'High')
newPriorityInput.appendChild(selectHigh);
const selectMedium = document.createElement('option');
selectMedium.textContent = "Medium";
newPriorityInput.appendChild(selectMedium);
const selectLow = document.createElement('option');
selectLow.textContent = "Low";
newPriorityInput.appendChild(selectLow);
newPriority.appendChild(newPriorityInput);
//button to submit new task to the project
const submitNewTaskBtn = document.createElement('button');
submitNewTaskBtn.textContent = "Add Task";
addTaskModal.appendChild(newTask);
addTaskModal.appendChild(newPriority);
addTaskModal.appendChild(submitNewTaskBtn);
export { addTaskModal };
export { submitNewTaskBtn };
Вот основной файл index.js, в котором у меня есть функция renderSidebar() для заполнения боковой панели списком проектов:
import './styles.css';
import { myProjects } from './myProjects.js';
import renderMain from './renderMain.js';
import createTask from './addTask.js';
import { addTaskModal } from './addTaskModal.js';
const mainContent = document.querySelector('#main');
const sideBar = document.querySelector('#sidebarproject');
function renderSidebar() {
let sidebarHTML = '';
myProjects.forEach((project, index) => {
sidebarHTML += `<div class = "projects" id = "project-${index}">${project.name}</div>`
})
sideBar.innerHTML += sidebarHTML;
const projects = document.querySelectorAll('.projects');
projects.forEach(project =>
project.addEventListener('click', renderMain)
)
}
renderSidebar();
mainContent.appendChild(addTaskModal);
я заметил
renderMain(event)
и
let index = parseInt(event.target.id.split('-')[1]);
Это не сработает, если событие, которое вы отправляете в rendermain, не имеет идентификатора, например, вашей кнопки удаления.
Я предлагаю тебе переехать
localStorage.setItem('projects', JSON.stringify(myProjects));
в rendermain и измените
function renderMain(event) {
let index = parseInt(event.target.id.split('-')[1]);
к
function renderMain(index,projectName)
Я ТАКЖЕ предлагаю вам делегировать щелчок контейнеру, тогда вы сможете сделать
deleteBtn.classList.add('delete');
deleteBtn.textContent = 'Delete Task';
deleteBtn.dataset.index = i;
deleteBtn.dataset.projectname = projectName;
и изменить
deleteBtn.addEventListener('click', () => {
myProjects[index].tasks.splice(i, 1);
localStorage.setItem('projects', JSON.stringify(myProjects));
renderMain(event)
})
к
mainContent.addEventListener('click', (e) => {
const tgt = e.target.closest('button.delete');
if (!tgt) return;
myProjects[tgt.dataset.index].tasks.splice(tgt.dataset.index, 1);
renderMain(tgt.dataset.index,tgt.dataset.projectname);
});
вне функции
Вот более простая версия вашего рендера
const renderSidebar => () {
sideBar.innerHTML = myProjects
.map((project, index) => `<div class = "projects" data-name = "${project.name}" data-index = "${index}">${project.name}</div>`).join('');
};
sideBar.addEventListener('click', (e) => {
const tgt = e.target.closest('div.projects');
if (!tgt) return; // we did not click in a project
renderMain(tgt.dataset.index, tgt.dataset.name)
})
В вашем модальном окне вам нужно захватить индекс
Вот изменения в addModal
submitNewTaskBtn.addEventListener('click', () => {
myProjects.tasks.push(newTask);
renderMain(myProjects.length-1,newTaskInput.value);
})
привет, mplungjan, большое спасибо за ответ! извините, если я не предоставил достаточно кода, я боялся, что он может быть обширным, я отредактирую сообщение, включив в него ту часть, которую вам не хватает. Попробую реализовать то, что вы уже предоставили. Еще раз спасибо!
Привет, mplungjan, я включил больше своего кода и заметил ваш вклад в renderMain(event). В предыдущем проекте я научился фиксировать индекс того, что я щелкнул таким образом. Итак, в моей функции renderSidebar() я Я установил идентификатор всех перечисленных проектов на боковой панели, используя их индексы. Я не уверен, как захватить индекс, не включая щелчок по событию в renderMain.
Что касается вашего вклада в захват индекса в моем модальном окне, я до сих пор не уверен, как захватить индекс активного проекта, поскольку ранее я получил индекс, щелкнув списки проектов на боковой панели.
Смотрите мое обновление. Возможно, это сработает не сразу, так как я опять же не могу протестировать это на рабочей версии, но суть вы поняли.
привет, я попробовал внедрить твое решение в свой код. Еще раз спасибо, что нашли время разобраться в этом.
привет, mplungjan, я потратил некоторое время на чтение вашего ответа, но есть некоторые вещи, которые я еще не узнал, например, как вы использовали .closest в функции renderSidebar. Я пока изучу эти вещи, прежде чем снова начну работать над проектом. Большое спасибо за помощь
Опубликуйте код в качестве минимального воспроизводимого примера и включите HTML.