Как настроить таргетинг на определенный элемент массива?

В настоящее время я работаю над списком дел из проекта 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);

Опубликуйте код в качестве минимального воспроизводимого примера и включите HTML.

zer00ne 28.06.2024 08:13
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

я заметил

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, большое спасибо за ответ! извините, если я не предоставил достаточно кода, я боялся, что он может быть обширным, я отредактирую сообщение, включив в него ту часть, которую вам не хватает. Попробую реализовать то, что вы уже предоставили. Еще раз спасибо!

Andrey 28.06.2024 08:15

Привет, mplungjan, я включил больше своего кода и заметил ваш вклад в renderMain(event). В предыдущем проекте я научился фиксировать индекс того, что я щелкнул таким образом. Итак, в моей функции renderSidebar() я Я установил идентификатор всех перечисленных проектов на боковой панели, используя их индексы. Я не уверен, как захватить индекс, не включая щелчок по событию в renderMain.

Andrey 28.06.2024 08:24

Что касается вашего вклада в захват индекса в моем модальном окне, я до сих пор не уверен, как захватить индекс активного проекта, поскольку ранее я получил индекс, щелкнув списки проектов на боковой панели.

Andrey 28.06.2024 08:28

Смотрите мое обновление. Возможно, это сработает не сразу, так как я опять же не могу протестировать это на рабочей версии, но суть вы поняли.

mplungjan 28.06.2024 09:07

привет, я попробовал внедрить твое решение в свой код. Еще раз спасибо, что нашли время разобраться в этом.

Andrey 28.06.2024 10:10

привет, mplungjan, я потратил некоторое время на чтение вашего ответа, но есть некоторые вещи, которые я еще не узнал, например, как вы использовали .closest в функции renderSidebar. Я пока изучу эти вещи, прежде чем снова начну работать над проектом. Большое спасибо за помощь

Andrey 28.06.2024 10:46

Другие вопросы по теме