Не работаеть добавления класа в элемент через if

const tasks = [
  { text: 'Buy milk' },
  { text: 'Pick up Tom from airport' },
  { text: 'Visit party' },
  { text: 'Visit doctor' },
  { text: 'Buy meat' },
];
const tasksNew = [];
const renderListItems = listItems => {
  const listElem = document.querySelector('.list');

  const listItemsElems = listItems
    .map(({text}) => {
      const listItemElem = document.createElement('li');
      listItemElem.classList.add('list__item');

      const checkboxElem = document.createElement('input');
      checkboxElem.setAttribute('type', 'checkbox');
      checkboxElem.classList.add('list__item-checkbox');
      console.log(checkboxElem);
      if (checkboxElem.checked) {
          listItemElem.classList.add('list__item_done');
      } else {
          listItemElem.classList.remove('list__item_done');
      }

      listItemElem.append(checkboxElem, text); 
      console.log(listItemElem);
      return listItemElem;
    })
    .sort((a, b) => a.classList.contains('list__item_done') - b.classList.contains('list__item_done'));

  listElem.append(...listItemsElems);
}

renderListItems(tasks);

Почему не работаеть добавления класа в элемент через if или как сделать правильно? И потом нужно правильно отсортировать так, чтоб если такой клас был, то элемент шел вниз списка?


Ответы (2 шт):

Автор решения: vsemozhebuty

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

Подробнее см. в https://learn.javascript.ru/events

Попробуйте что-то вроде этого:

const tasks = [
  { text: 'Buy milk' },
  { text: 'Pick up Tom from airport' },
  { text: 'Visit party' },
  { text: 'Visit doctor' },
  { text: 'Buy meat' },
];

const tasksNew = [];
const renderListItems = listItems => {
  const listElem = document.querySelector('.list');

  const listItemsElems = listItems
    .map(({ text }) => {
      const listItemElem = document.createElement('li');
      listItemElem.classList.add('list__item');

      const checkboxElem = document.createElement('input');
      checkboxElem.setAttribute('type', 'checkbox');
      checkboxElem.classList.add('list__item-checkbox');

      listItemElem.append(checkboxElem, text);
      return listItemElem;
    });

  listElem.append(...listItemsElems);
};

renderListItems(tasks);

document.addEventListener('change', (event) => {
  if (event.target.className !== 'list__item-checkbox') return;

  if (event.target.checked) {
      event.target.parentElement.classList.add('list__item_done');
  } else {
      event.target.parentElement.classList.remove('list__item_done');
  }

  document.querySelector('.list').append(
    ...[...document.querySelectorAll('li.list__item')]
         .sort((a, b) => a.classList.contains('list__item_done') - b.classList.contains('list__item_done'))
  );
})
<ul class='list'></ul>

→ Ссылка
Автор решения: Neomaster

Подправил ваш код без использования addEventListener(). Добавил функцию установки/удаления класса и сортировки. Комментарии внутри кода.

    const tasks = [
        { text: 'Buy milk' },
        { text: 'Pick up Tom from airport' },
        { text: 'Visit party' },
        { text: 'Visit doctor' },
        { text: 'Buy meat' }
    ];

// Для вызова функции markAndRefresh() для элемента,
// которая добавляет класс чекнутому элементу списка.
var idValue = 0;

const tasksNew = [];
const renderListItems = listItems => {
    const listElem = document.querySelector('.list');
    const listItemsElems = listItems
        .map(({text}) => {
            const listItemElem = document.createElement('li');
            listItemElem.classList.add('list__item');

            const checkboxElem = document.createElement('input');
            checkboxElem.setAttribute('type', 'checkbox');

            // Для выделения и сортировки.
            checkboxElem.setAttribute('id', idValue);
            checkboxElem.setAttribute('onclick', 'markAndRefresh(' + idValue++ + ')');

            checkboxElem.classList.add('list__item-checkbox');
            //console.log(checkboxElem); Мешает.
      
            // Этот код действует только при создании элементов.
            // По умолчанию они все не чекнуты.
            // Поэтому он бесполезен.
            /*
            if (checkboxElem.checked) {
                listItemElem.classList.add('list__item_done');
            } else {
                listItemElem.classList.remove('list__item_done');
            }*/

            listItemElem.append(checkboxElem, text); 
            //console.log(listItemElem);
            return listItemElem;
        })
        // По той же причине бесполезен и этот.
        /*
        .sort((a, b) => a.classList.contains('list__item_done') - b.classList.contains('list__item_done'))
        */
        ;
    
    listElem.append(...listItemsElems);
}

renderListItems(tasks);

// Добавлено.
// Если список один, то лучше использовать id='list'.
list = document.getElementsByClassName('list')[0];

// Добавляет или удаляет класс у чекнутого элемента
// в зависимости от полученного значения.
var markAndRefresh = function(id){
    var listItems = document.getElementsByClassName('list__item-checkbox');
    var parent = document.getElementById(id).parentNode;

    if (parent.classList.contains('list__item_done')) 
    {
        parent.classList.remove('list__item_done');
    }else{
        parent.classList.add('list__item_done');
    }
    
    var topItems = [];
    var bottomItems = [];
    for (var i = 0; i < listItems.length; i++) {
        if (listItems[i].parentNode.classList.contains('list__item_done') == true){
            topItems.push(listItems[i].parentNode); 
        }else{
            bottomItems.unshift(listItems[i].parentNode);
        }
    }
    for (var i = 0; i < topItems.length; i++) {
        list.append(topItems[i]);
    }
    for (var i = 0; i < bottomItems.length; i++) {
        list.append(bottomItems[i]);
    }
}
.list__item_done{
        color: green;
    }
<div class="list"></div>

→ Ссылка