Сравнение ввода с пустой строкой

Существует сайт с функционалом добавления карточек для различных дел (блокнот):

var addButton = document.getElementById("add-task-submit");
var taskList = document.getElementById("task-list")

//класс инфы о задаче//
class Task {
  constructor(name, description, priority, deadline) {
    this.name = name;
    this.description = description;
    this.priority = priority;
    this.deadline = deadline;
  }
}

//класс который создает один из 4 "компонентов" задачи//
class TaskComponent {
  constructor(innertext, style, type) {
    this.innertext = innertext;
    this.style = style;
    this.type = type;

    this.component = document.createElement(this.type);
    this.component.classList.add(this.style);
    this.component.appendChild(document.createTextNode(this.innertext));
    taskCard.appendChild(this.component);
  }
}

//функция для кнопки "выполнено"//
function taskDone(event) {
  this.button = event.target;
  let taskCard = this.button.parentElement;
  let taskList = taskCard.parentElement;
  taskList.removeChild(taskCard);
}

//ивент на создачу задачи//
addButton.addEventListener('click', function(event) {
  let task = new Task(
    `${document.getElementById("add-task-name").value}`,
    `${document.getElementById("add-task-description").value}`,
    `${document.getElementById("add-task-priority").value}`,
    `${document.getElementById("add-task-deadline").value}`,
  )
  console.log(task)

  //создание самой карточки//
  taskCard = document.createElement("div");
  taskCard.classList.add("task-card");

  //создание каждого элемента в карточке//
  taskName = new TaskComponent(task.name, "task-name", "h2");
  console.log(taskName);

  taskDescription = new TaskComponent(task.description, "task-description", "div");
  console.log(taskDescription);

  taskPriority = new TaskComponent(`Приоритет: ` + task.priority, "task-priority", "div");
  console.log(taskPriority);

  taskDeadline = new TaskComponent(`Выполнить до: ` + task.deadline, "task-deadline", "div");
  console.log(taskDeadline);

  doneButton = document.createElement("button");
  doneButton.classList.add("task-done");
  doneButton.appendChild(document.createTextNode('Выполнить'));
  taskCard.appendChild(doneButton);
  doneButton.addEventListener('click', taskDone);

  taskList.insertBefore(taskCard, taskList.childNodes[0]);
  event.preventDefault();
})
<header>
  <div class="header-content">
    <h1>Динамическое добавление компонентов</h1>
  </div>
</header>
<main>
  <form id="add-task-form">
    <h1>Новая задача</h1>
    <div class="input-wrapper">
      <label for="add-task-name">Задача</label>
      <input type="text" id="add-task-name" pattern="^.+$" required>
    </div>
    <div class="input-wrapper">
      <label for="add-task-description">Описание</label>
      <input type="text" id="add-task-description">
    </div>
    <div class="input-wrapper">
      <label for="add-task-priority">Приоритет</label>
      <select id="add-task-priority">
        <option value="Очень Высокий">Очень Высокий</option>
        <option value="Высокий">Высокий</option>
        <option value="Средний" selected>Средний</option>
        <option value="Низкий">Низкий</option>
        <option value="Очень Низкий">Очень Низкий</option>
      </select>
    </div>
    <div class="input-wrapper">
      <label for="add-task-deadline">Дедлайн</label>
      <input type="datetime-local" id="add-task-deadline">
    </div>
    <div class="input-wrapper">
      <input type="submit" value="Добавить" id="add-task-submit">
    </div>
  </form>
</main>
<div id="task-list">
</div>

Однако, пользователь может как поставить taskDescription/taskDeadline на задачу, так и не ставить их. Соответственно, в случаях где инпут поле дедлайна и описания остается не заполненным, нужно не создавать элементы в карточку такой задачи, вопрос: как понять что пользователь сайта оставил эти поля незаполненными и не создавать под них дивы? На данный момент если эти поля не заполнены, то все равно создается див со словами "Выполнить до:"

Неправильный вариант

Неправильный вариант

Как должно быть

должно быть


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

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

Например так

 taskDeadline = task.deadline && new TaskComponent(`Выполнить до: ` + task.deadline, "task-deadline", "div");
  
→ Ссылка
Автор решения: EzioMercer

Я сделал небольшой рефакторинг, надеюсь будет полезно:

  • Первое от чего я избавился - это от приведения значения инпута value к типу строки т.к. значение инпута и так уже строка не надо с ним ничего делать

  • Избавился от классов. Не поймите неправильно, что классы вообще не нужны, но они не нужны в том виде, в котором вы их используете или показываете нам. Вы объявляли класс, а потом работали только лишь в конструкторе и возвращали объект или выполняли какие-то действия, которые к классу не имели никакого отношения. Классы полезны, когда вы хотите описать структуру, когда вам нужны методы у всех экземпляров класса и т.д. Создавать класс, чисто чтобы там хранить информацию - это ничем не лучше хранения информации в обычном объекте

  • Переделал функции в стрелочные функции. Это никакой объективной пользы не несёт, просто с ними мне удобнее работать

  • Всё что можно было вынести в глобальные переменные вынес, чтобы повторно их из дома не доставать, например taskNameInput

  • Избавился от глобальной переменной taskCard, у вас не было с этим проблем, но поверьте работать с такими глобальными переменными, в других функциях, переписывать их значения и т.д. - ОЧЕНЬ опасно и отлавливать порой бывает сложновато, кто и где поставил ненужное значение. Лучше передать в нужные функции написав одной переменной больше и быть в безопасности

  • Не привыкайте слушать click у кнопки сабмита формы. Лучше слушать само событие submit напрямую у формы

  • e.preventDefault() обычно пишут прямо в самом начале потому перенёс его туда

Я бы решил эту проблему чуть иначе:

  • Для начала важно знать, что строка заполненная только пробелами - валидна в JS. В том смысле, что JS может рассматривать такую строку как строку, которую можно представить как true. По этой причине, когда вы напишите task.deadline && что-то, то у вас опять будет "Неправильный вариант". И я предполагаю, что вы бы хотели избежать такого, потому при проверке я сначала применяю метод trim, который, с начала и с конца строки убирает все пробелы. Так я гарантированно исключу строку, которая наполнена только пробелами. Но заметье, что только при проверке я убираю ненужные пробелы, т.к. в целом вам может быть не надо будет избавляться от лишних пробелов например в строке Петя

  • Если я правильно понял, то вам может понадобиться скрывать не одно поле, а несколько полей, если в соответсвующие инпуты ничего не было написано. В таком случае вам придётся везде писать что-то типа task.deadline && что-то, что во первых не всегда корректно отрабатывает (как мы выяснили в предыдущем пункте), а так же код будет некрасивым (да, это субъективным может показаться) как минимум потому что надо будет не забыть его везде прописать. Вашу проблему решил, как по мне более универсальным способом, вынеся проверку в саму функцию добавления. Правда из-за этого у меня на 1 больше аргумент стал отправляться, но зато проверка единая для всех

  • Этот дополнительный аргумент типа (text) => ${text} - простая стрелочная функция, которая на вход принимает любую строку и возвращает в нужном виде. Применяется она в этой строке textTmp(innerText), где innerText - это значение инпута

const addFrom = document.getElementById('add-task-form');
const taskList = document.getElementById('task-list');
const taskNameInput = document.getElementById('add-task-name');
const taskDescriptionInput = document.getElementById('add-task-description');
const taskPriorityInput = document.getElementById('add-task-priority');
const taskDeadlineInput = document.getElementById('add-task-deadline');

//класс инфы о задаче//
const taskData = (name, description, priority, deadline) => ({
  name,
  description,
  priority,
  deadline,
})

//класс который создает один из 4 "компонентов" задачи//
const createTaskComponent = (appendTo, textTmp, innerText, style, type) => {
  if (innerText.trim() === '') return;

  const component = document.createElement(type);
  component.classList.add(style);
  component.appendChild(document.createTextNode(textTmp(innerText)));
  
  appendTo.appendChild(component);
}

//функция для кнопки "выполнено"//
const taskDone = (e) => {
  const target = e.target;
  const taskCard = target.parentElement;
  
  taskList.removeChild(taskCard);
}

//ивент на создачу задачи//
addFrom.addEventListener('submit', (e) => {
  e.preventDefault();

  const task = taskData(
    taskNameInput.value,
    taskDescriptionInput.value,
    taskPriorityInput.value,
    taskDeadlineInput.value,
  )

  //создание самой карточки//
  const taskCard = document.createElement('div');
  taskCard.classList.add('task-card');

  //создание каждого элемента в карточке//
  createTaskComponent(taskCard, (text) => `${text}`, task.name, 'task-name', 'h2');
  createTaskComponent(taskCard, (text) => `${text}`, task.description, 'task-description', 'div');
  createTaskComponent(taskCard, (text) => `Приоритет: ${text}`, task.priority, 'task-priority', 'div');
  createTaskComponent(taskCard, (text) => `Выполнить до: ${text}`, task.deadline, 'task-deadline', 'div');

  doneButton = document.createElement('button');
  doneButton.classList.add('task-done');
  doneButton.appendChild(document.createTextNode('Выполнить'));
  taskCard.appendChild(doneButton);
  doneButton.addEventListener('click', taskDone);

  taskList.insertBefore(taskCard, taskList.childNodes[0]);
})
<header>
  <div class="header-content">
    <h1>Динамическое добавление компонентов</h1>
  </div>
</header>
<main>
  <form id="add-task-form">
    <h1>Новая задача</h1>
    <div class="input-wrapper">
      <label for="add-task-name">Задача</label>
      <input type="text" id="add-task-name" pattern="^.+$" required>
    </div>
    <div class="input-wrapper">
      <label for="add-task-description">Описание</label>
      <input type="text" id="add-task-description">
    </div>
    <div class="input-wrapper">
      <label for="add-task-priority">Приоритет</label>
      <select id="add-task-priority">
        <option value="Очень Высокий">Очень Высокий</option>
        <option value="Высокий">Высокий</option>
        <option value="Средний" selected>Средний</option>
        <option value="Низкий">Низкий</option>
        <option value="Очень Низкий">Очень Низкий</option>
      </select>
    </div>
    <div class="input-wrapper">
      <label for="add-task-deadline">Дедлайн</label>
      <input type="datetime-local" id="add-task-deadline">
    </div>
    <div class="input-wrapper">
      <input type="submit" value="Добавить" id="add-task-submit">
    </div>
  </form>
</main>
<div id="task-list">
</div>

Если вдруг вам не нужна будет поддержка IE, то можно рефакторить код дальше :) Например:

  • Я переписал бы все removeChild-ы, appendChild-ы и insertBefore на remove-ы, append-ы и prepend соответственно. С ними намного удобнее работать

  • Не нужно объявлять 100500 ненужных переменных, чтобы собирать значения инпутов у формы. Теперь за нас всю эту грязную работу может делать FormData. И нужда в вашем class Task полностью отпадает

const addFrom = document.getElementById('add-task-form');
const taskList = document.getElementById('task-list');

//класс который создает один из 4 "компонентов" задачи//
const createTaskComponent = (appendTo, textTmp, innerText, style, type) => {
  if (innerText.trim() === '') return;

  const component = document.createElement(type);
  component.classList.add(style);
  component.append(textTmp(innerText));
  
  appendTo.append(component);
}

//функция для кнопки "выполнено"//
const taskDone = (e) => e.target.parentElement.remove();

//ивент на создачу задачи//
addFrom.addEventListener('submit', (e) => {
  e.preventDefault();

  const taskData = new FormData(e.target);

  //создание самой карточки//
  const taskCard = document.createElement('div');
  taskCard.classList.add('task-card');

  //создание каждого элемента в карточке//
  createTaskComponent(taskCard, (text) => `${text}`, taskData.get('name'), 'task-name', 'h2');
  createTaskComponent(taskCard, (text) => `${text}`, taskData.get('description'), 'task-description', 'div');
  createTaskComponent(taskCard, (text) => `Приоритет: ${text}`, taskData.get('priority'), 'task-priority', 'div');
  createTaskComponent(taskCard, (text) => `Выполнить до: ${text}`, taskData.get('deadline'), 'task-deadline', 'div');

  const doneButton = document.createElement('button');
  doneButton.classList.add('task-done');
  doneButton.append('Выполнить');
  taskCard.append(doneButton);
  doneButton.addEventListener('click', taskDone);

  taskList.prepend(taskCard, taskList.childNodes[0]);
})
<header>
  <div class="header-content">
    <h1>Динамическое добавление компонентов</h1>
  </div>
</header>
<main>
  <form id="add-task-form">
    <h1>Новая задача</h1>
    <div class="input-wrapper">
      <label for="add-task-name">Задача</label>
      <input type="text" id="add-task-name" name="name" pattern="^.+$" required>
    </div>
    <div class="input-wrapper">
      <label for="add-task-description">Описание</label>
      <input type="text" id="add-task-description" name="description">
    </div>
    <div class="input-wrapper">
      <label for="add-task-priority">Приоритет</label>
      <select id="add-task-priority" name="priority">
        <option value="Очень Высокий">Очень Высокий</option>
        <option value="Высокий">Высокий</option>
        <option value="Средний" selected>Средний</option>
        <option value="Низкий">Низкий</option>
        <option value="Очень Низкий">Очень Низкий</option>
      </select>
    </div>
    <div class="input-wrapper">
      <label for="add-task-deadline">Дедлайн</label>
      <input type="datetime-local" id="add-task-deadline" name="deadline">
    </div>
    <div class="input-wrapper">
      <input type="submit" value="Добавить" name="add-task-submit">
    </div>
  </form>
</main>
<div id="task-list">
</div>

→ Ссылка