Задать вопрос
  • Какую логику сделать для проверки верности вопроса в приложении тест?

    0xD34F
    @0xD34F Куратор тега React
    Начать следует не с какой-то там логики, а со структуры данных, что содержит вопросы. То, что есть сейчас, никуда не годится. Что, если завтра вместо трёх вариантов ответа надо будет сделать четыре? Будете добавлять ещё по два свойства в каждый объект в массиве вопросов, а в компоненте закопипастите ещё один input? А если в разных вопросах должно будет быть разное количество вариантов ответа? Что тогда?

    Варианты ответа складываете в массив, а корректный вариант обозначаете через его индекс:

    const questions = [
      {
        text: 'Выберите верное утверждение',
        answers: [
          'СССР распался в 1997 году',
          'Солнце вращается вокруг Земли',
          'шестью восемь - двадцать три',
        ],
        correctAnswer: 1,
      },
      {
        text: '...',
        answers: [ '...', '...', ... ],
        correctAnswer: ...,
      },
      ...
    ];

    В компоненте вопроса вместо того, чтобы копипастить input'ы, делаете цикл по вариантам ответа:

    function Question(props) {
      const onChange = e => props.onAnswerChange(+e.target.value);
    
      return (
        <div>
          <h3>{props.question.text}</h3>
          <ol>
            {props.question.answers.map((n, i) => (
              <li>
                <label>
                  <input
                    type="radio"
                    value={i}
                    checked={props.answer === i}
                    onChange={onChange}
                  />
                  {n}
                </label>
              </li>
            ))}
          </ol>
        </div>
      );
    }

    В родительском компоненте храните массив ответов:

    function App(props) {
      const [ answers, setAnswers ] = useState(Array(props.questions.length).fill(null));
    
      const updateAnswer = (questionIndex, answer) =>
        setAnswers(answers.map((n, i) => i === questionIndex ? answer : n));
    
      return (
        <div>
          {props.questions.map((n, i) => (
            <Question
              question={n}
              answer={answers[i]}
              onAnswerChange={answer => updateAnswer(i, answer)}
            />
          ))}
        </div>
      );
    }

    Ну и возвращаясь к вашему вопросу, чего там надо было?

    не получается сделать грамотную проверку правильного ответа...

    Чтобы проверить правильность ответа, надо сравнить его со значением свойства correctAnswer у соответствующего (с тем же индексом) вопроса. Например, считаем количество правильных ответов:

    const correctAnswersCount = answers.reduce((acc, n, i) => {
      return acc + (n === questions[i].correctAnswer);
    }, 0);

    ...и одновременно вывести верные ответы

    Поскольку свойство, обозначающее правильный ответ, является его индексом, просто достаём соответствующие элементы из массивов с вариантами ответа:

    const correctAnswers = questions.map(n => n.answers[n.correctAnswer]);

    Ну а массив строк вывести - надеюсь, справитесь сами.

    UPD. Посмотреть живьём можно здесь (есть отличия от того, что есть или предполагается у вас - вопросы показываются по очереди, а не все сразу; в результатах отображаются только верные ответы).
    Ответ написан
    1 комментарий
  • Как изменить иконку курсора, когда перетаскиваем элемент по сайту?

    0xD34F
    @0xD34F Куратор тега CSS
    селектор перетаскиваемого элемента:active {
      cursor: что сюда можно вписать, смотрите здесь - developer.mozilla.org/en-US/docs/Web/CSS/cursor
    }
    Ответ написан
    Комментировать
  • Как изменить атрибут строки в таблице по нажатию?

    0xD34F
    @0xD34F Куратор тега Vue.js
    :readonly="`${item.isReadonly}`"

    Ну и зачем в строку его засовывать? Вместо false будет "false", а булевым эквивалентом любой непустой строки является true.
    Ответ написан
  • Как сделать выборку json из postgres?

    0xD34F
    @0xD34F
    Есть поле desc

    А ещё есть ключевое слово desc. Ну, для задания направления сортировки. Как думаете, может ошибка случатся от того, что ключевое слово desc находится в неположенном месте?

    Оберните свой desc в двойные кавычки. А лучше - переименуйте столбец.
    Ответ написан
    1 комментарий
  • Как создать активность только одного элемента из многих?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Активность кнопки пусть задаётся извне:

    props: {
      active: Boolean,
    },

    В родителе должно быть свойство, указывающее, кто активен (хранит индекс/имя/id - что-то, что имеет уникальное значение для каждой из кнопок):

    data: () => ({
      active: null,
    }),

    Активность конкретной кнопки вычисляете в зависимости от равенства упомянутой выше уникальной характеристики кнопок значению свойства активности; по клику переключаете значение активности:

    <v-button
      v-for="i in 3"
      :active="active === i"
      @click="active = active === i ? null : i"
    >
    Ответ написан
    1 комментарий
  • Когда применять arr.reduce?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Когда сочтёте нужным. Типа, подумали, и решили - здесь reduce нужен. Или не нужен. Да, подумали. Для этого у вас есть особый инструмент - голова называется.
    Ответ написан
    Комментировать
  • Как в таблице element-plus преобразовать данные при выводе?

    0xD34F
    @0xD34F Куратор тега Vue.js
    <el-table-column prop="block" label="Block">
      <template #default="{ row }">
        {{ row.block ? 'hello, world!!' : 'fuck the world' }}
      </template>
    </el-table-column>
    Ответ написан
    Комментировать
  • Как превратить данные input в массив js?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const data = Array.prototype.reduce.call(
      document.querySelectorAll('input'),
      (acc, n) => {
        const keys = n.name.match(/\w+/g);
        const key = keys.pop();
        keys.reduce((p, c) => p[c] ??= {}, acc)[key] = n.value;
        return acc;
      },
      {}
    );
    Ответ написан
    Комментировать
  • Как сделать кастомный выпадающий список?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вместо назначения индивидуальных обработчиков клика элементам списка (которых в момент назначения ещё нет, openItems оказывается пуст, так что обработчики никому не назначаются) сделайте один делегированный, надо

    openItems.forEach(function (formItem) {
      formItem.addEventListener('click', function () {
        openBtn.innerText = this.innerText;
        openList.classList.remove('open');
        hiddenInput.value = this.dataset.value;
      });
    });

    заменить на

    openList.addEventListener('click', function(e) {
      const item = e.target.closest('li.form-item');
      if (item) {
        openBtn.innerText = item.innerText;
        openList.classList.remove('open');
        hiddenInput.value = item.dataset.value;
      }
    });
    Ответ написан
    1 комментарий
  • Как изменить цвет нижней направляющей в графике chart.js?

    0xD34F
    @0xD34F
    есть свойство для изменения ее цвета, но если убрать сетку с заднего фона, то это свойство не работает

    А у меня всё работает, сравнивайте со своим вариантом (кстати, а почему не показали?), ищите у себя косяки, исправляйте их:

    options: {
      scales: {
        x: {
          grid: {
            display: false,
            borderColor: 'red',
          },
        },
        y: {
          grid: {
            display: false,
            drawBorder: false,
          },
        },
      },
    },
    Ответ написан
    Комментировать
  • Как получить последовательно разницу значений в массиве?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Собрать новый массив:

    const newData = data.map((n, i, a) => ({
      ...n,
      newSick: n.sick - (i < ~-a.length && a[-~i].sick),
    }));

    Добавить свойство элементам существующего массива:

    data.forEach((n, i, a) => n.newSick = n.sick - (a[i + 1]?.sick ?? 0));
    // или
    data.reduceRight((prev, n) => (n.newSick = n.sick - prev, n.sick), 0);
    Ответ написан
    Комментировать
  • Как отсортировать массив пар [ключ, значение]?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const sorted = (arr, key) => arr
      .map(n => [ key(n), n ])
      .sort(([a], [b]) => a < b ? -1 : +(a > b))
      .map(n => n[1]);

    Так как сортировка сбивается из-за наличия нечисловых символов в начале некоторых строк, просто вырежем их:

    const sortedArr = sorted(arr, n => n[0].replace(/^\D+/, ''));

    Если же значения могут быть не только двухзначными, то сравнивать их как строки уже нельзя. Делаем из них настоящие числа, считаем сумму; если второе слагаемое отсутствует, используем первое повторно:

    const sortedArr = sorted(arr, n => {
      const d = n[0].match(/\d+/g);
      return +d[0] + +d.at(-1);
    });
    Ответ написан
    Комментировать
  • Как указать активность элемента?

    0xD34F
    @0xD34F Куратор тега React
    В качестве дефолтного значения для activeType указывайте не 0, а нулевой элемент из types:

    React.useState(0); ---> React.useState(types[0]);
    Ответ написан
    1 комментарий
  • Как двигать блок по квадрату?

    0xD34F
    @0xD34F
    Как сделать, чтобы третье условие работало?

    Усилить первое условие так, чтобы оно не становилось истинным после того, как перестаёт быть истинным второе.

    Только вам это мало чем поможет - кривое условие не только первое, но и третье.
    А всего их должно быть четыре.

    const rectLeftTop = [ 50, 50 ];
    const rectSize = 450;
    const step = 15;
    let [ x, y ] = rectLeftTop;
    
    setInterval(() => {
      if (rectLeftTop[1] <= y && x === rectLeftTop[0]) {
        y = Math.min(y + step, rectLeftTop[1] + rectSize);
      }
    
      if (rectLeftTop[0] <= x && y === rectLeftTop[1] + rectSize) {
        x = Math.min(x + step, rectLeftTop[0] + rectSize);
      }
    
      if (rectLeftTop[1] < y && x === rectLeftTop[0] + rectSize) {
        y = Math.max(y - step, rectLeftTop[1]);
      }
    
      if (rectLeftTop[0] < x && y === rectLeftTop[1]) {
        x = Math.max(x - step, rectLeftTop[0]);
      }
    
      block.style.left = `${x}px`;
      block.style.top = `${y}px`;
    }, rectSize / step);

    https://jsfiddle.net/efzcpda7/

    Хотя есть вариант обойтись одним.

    const directions = [
      [  0, -1 ],
      [ -1,  0 ],
      [  0,  1 ],
      [  1,  0 ],
    ];
    let iDirection = 0;
    
    const coords = [ 50, 50 ];
    const step = 15;
    const rectSize = 450;
    const rect = [ [...coords], coords.map(n => n + rectSize) ];
    
    (function move() {
      const d = directions[iDirection].map(n => n * step);
      coords.forEach((n, i, a) => a[i] = Math.max(rect[0][i], Math.min(rect[1][i], n + d[i])));
    
      if (coords.every((n, i) => rect.some(m => m[i] === n))) {
        iDirection = (iDirection + 1) % directions.length;
      }
    
      block.style.left = `${coords[0]}px`;
      block.style.top = `${coords[1]}px`;
    
      requestAnimationFrame(move);
    })();

    https://jsfiddle.net/efzcpda7/1/

    Но вообще - никакие условия не нужны.

    Можно задать блоку transition, определить массив конечных координат и устанавливать следующие после достижения предыдущих (событие transitionend):

    .block {
      transition: all 750ms linear;
    }

    const positions = [
      [  50,  50 ],
      [  50, 500 ],
      [ 500, 500 ],
      [ 500,  50 ],
    ];
    let iPosition = -1;
    
    move();
    block.addEventListener('transitionend', move);
    setTimeout(move, 0);
    
    function move() {
      iPosition = (iPosition + 1) % positions.length;
      const [ x, y ] = positions[iPosition].map(n => `${n}px`);
      block.style.left = x;
      block.style.top = y;
    }

    https://jsfiddle.net/efzcpda7/2/

    Да и в целом, JS не нужен - перемещения блока можно описать в CSS.

    .block {
      animation: move 3s infinite linear;
    }
    
    @keyframes move {
      0%, 100% {
        left: 50px;
        top: 50px;
      }
      25% {
        left: 50px;
        top: 500px;
      }
      50% {
        left: 500px;
        top: 500px;
      }
      75% {
        left: 500px;
        top: 50px;
      }
    }

    https://jsfiddle.net/efzcpda7/3/

    Если подумать, то и стили тоже лишние - с задачей отлично справляется SVG.

    <svg viewBox="0 0 550 550" xmlns="http://www.w3.org/2000/svg" width="550" height="550">
      <rect width="50" height="50" fill="red">
        <animateMotion
          dur="3s"
          repeatCount="indefinite"
          path="M50,50 L50,500 L500,500 L500,50 L50,50 z"
        />
      </rect>
    </svg>

    https://jsfiddle.net/efzcpda7/4/
    Ответ написан
    Комментировать
  • Как сложить значения массива по условию?

    0xD34F
    @0xD34F
    $grouped = [];
    
    foreach ($items as $n) {
      $grouped[$n['type']] ??= [
        'type' => $n['type'],
        'typeAmount' => 0,
        'amount' => 0,
      ];
    
      $grouped[$n['type']]['typeAmount'] += $n['typeAmount'];
      $grouped[$n['type']]['amount'] += $n['amount'];
    }
    
    $grouped = array_values($grouped);
    Ответ написан
    Комментировать
  • Как в React Native Calendars от wix сделать начало недели с понедельника?

    0xD34F
    @0xD34F
    Неужели было так трудно заглянуть в документацию самостоятельно?
    Ответ написан
    Комментировать
  • Почему не передаются данные через V-model?

    0xD34F
    @0xD34F Куратор тега Vue.js
    V-model="filterPriceFrom"

    V-model="filterPriceTo"

    props:['FilterPriceFrom', 'FilterPriceTo', "FilterCategoryId"],

    Во-первых - серьёзно? Не видите разницы между большими и маленькими буквами? Это как? О том, что буквы бывают большие и маленькие, и что это не одно и то же, рассказывают в первом классе. Вам сколько лет, шесть? Пять?

    Во-вторых, если бы вы составили себе труд открыть документацию, и прочесть, что там написано, то знали бы, что использовать v-model совместно с входными параметрами особого смысла нет. Потому что

    Все входные параметры образуют одностороннюю привязку между дочерним свойством и родительским: когда родительское свойство обновляется — оно будет передаваться дочернему, но не наоборот.

    Вот вам и ответ на ваш вопрос: данные не передаются потому, что не могут передаваться избранным вами способом, так уж устроен vue.

    Теперь, что делать.

    Внутри компонента заменяете все v-model="параметр" на

    :value="параметр" @input="$emit('update:параметр', $event.target.value)"

    Снаружи - привязываете значения с использованием модификатора sync, если используете вторую версию vue.
    Или, через v-model с указанием имени параметра, в случае vue 3.
    Ответ написан
    Комментировать
  • Как добавить или отнять 1 по клику на кнопки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    let count = 0;
    const countEl = document.querySelector('.text');
    const buttons = [...document.querySelectorAll('.click')];
    const onClick = e => updateCount(e.target.classList.toggle('clicked') ? 1 : -1);
    const updateCount = change => countEl.innerText = count += change;
    buttons.forEach(n => n.addEventListener('click', onClick));
    updateCount(buttons.reduce((acc, n) => acc + n.classList.contains('clicked'), 0));
    Ответ написан
    1 комментарий