Как динамически обновлять переменную экземпляра с помощью форм?

Я работаю над своим первым проектом RoR 7.1.3.2 и создал простую форму для приема заказов клиентов. У меня есть переменная экземпляра @total, и я хочу иметь возможность обновлять эту сумму, чтобы она была равна сумме всех полей number_fields, чтобы я получал общее количество заказанных товаров. Я хочу, чтобы это обновлялось каждый раз, когда обновляется поле number_field в форме, чтобы клиенты могли получить точное количество товаров, которые они покупают, при заполнении формы.

Я не очень хорошо знаю JavaScript, но возился с ним, но, честно говоря, я не уверен, как получить доступ к переменным экземпляра из Javascript. Я знаю, что могу обновить текстовый контекст div, но мне бы очень хотелось иметь возможность иметь переменную экземпляра, а не просто выводить текст, таким образом я могу использовать эту переменную для более удобного взаимодействия с моей базой данных.

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

Я просматривал документацию, правда, но думаю, что просто не знаю, где искать, поскольку ничего не нашел по этому поводу. Буду признателен за любую помощь. Вот мой код:

<div class  = "mt-2">
  <%= form_with model: @order do |form| %>
    <%= form.hidden_field "user", value: current_user.id %>
    <% @total = 0.00 %>   
    <% @items.each do |item| %>
      <%= form.fields_for OrderToItem.new, index: item.id do |item_form| %>
        <div><%= item_form.label :amount, item.name %></div>
        <div><%= item_form.number_field :amount, min: 0 %></div>
        <div><%= item_form.hidden_field :id, value: item.id %></div>
        <br>
      <% end %>
    <% end %> 

    <div><%= number_to_currency(@total, unit: "$", precision: 2) %></div>
    <%= form.submit "Submit Order", class: "bg-amber-950 rounded-xl p-2 mt-2 font-bold text-white" %>
  <% end %>
</div>

Когда требуется что-то динамичное, я предпочитаю интегрировать какой-нибудь js-компонент реакции/vue/что-нибудь еще, чтобы вы могли поместить всю форму внутри js-компонента.

Anton Bogdanov 29.03.2024 05:00

После рендеринга страница @total больше не существует. Вам понадобится какой-то JavaScript, чтобы поддерживать динамический промежуточный итог.

engineersmnky 29.03.2024 15:06

@engineersmnky Ах, понятно, ценю это. Тогда я, вероятно, рассмотрю некоторые вещи, связанные с JavaScript. Цените комментарий

Ignacio Cabero 29.03.2024 17:24

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

max 31.03.2024 19:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Добавить событие для поля суммы

<div><%= item_form.number_field :amount, min: 0, onchange: "updateTotal()" %></div>

Добавить идентификатор к элементу, отображающему общую сумму:

<div id = "total"><%= number_to_currency(@total, unit: "$", precision: 2) %></div>

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

<script>
  function updateTotal() {
    var total = 0;
    document.querySelectorAll('[name$ = "[amount]"]').forEach(function(input) {
      total += parseFloat(input.value) || 0;
    });
    document.getElementById('total').innerText = "$" + total.toFixed(2);
  }
</script>

Это псевдокод, возможно, вам придется его немного отредактировать и выполнить рефакторинг.

Огромное спасибо! Просто любопытно, есть ли лучшее место, где можно найти документацию по таким вещам? Я не уверен, где именно искать эти вещи.

Ignacio Cabero 01.04.2024 20:31

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

В форму я добавил эту строку (я использую Tailwind для CSS)

<div class = "hidden", id = "price_<%= item.id %>">0</div>

Это простой скрытый элемент div, который отслеживает цену каждого отдельного товара на основе его идентификатора. За пределами формы я добавил эту строку

 <div id = "total">$0.00</div>

В числовое поле моей формы я добавил oninput: для вызова функции javascript с именем updateTotal() всякий раз, когда изменяется входное значение.

<div><%= item_form.number_field :amount, min: 0, oninput: "updateTotal(this, #{item.id}, #{item.price})" %></div>

Я добавил раздел javascript на свою страницу

<script>
function updateTotal(input, id, price) {
  var item_total = 0;
  item_total += parseFloat(input.value)*price || 0;
  document.getElementById("price_" + id).innerText = item_total.toFixed(2);
  
  var total = 0;
  var priceDivs = document.querySelectorAll('div[id^ = "price_"]');
  priceDivs.forEach(function(div) {
    total += parseFloat(div.innerText);
  });
  document.getElementById("total").innerText = "$" + total.toFixed(2);
}
</script>

Скрипт в основном вычисляет цену для каждого товара и обновляет связанный с ним элемент div. Затем каждый из этих элементов суммируется и помещается в элемент с идентификатором «total».

Надеюсь, это поможет кому-нибудь еще!

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

Rails 7 с Turbo и jQuery не работает/работает только при первой загрузке страницы
Передайте идентификатор div в функцию javascript, чтобы отобразить несколько диаграмм d3 на странице
ActionDispatch::Http::MimeNegotiation::InvalidType («html» не является допустимым типом MIME):
Один контроллер Stimulus не загружается после переноса приложения Rails 7 на importmaps
Частичный рендеринг с турбопотоком не работает в Rails 7
Необработанная синтаксическая ошибка: запрошенный модуль «trix» не предоставляет экспорт с именем «default» (в youtube.js:1:8) в рельсах 7.1 при попытке редактирования trix
Переопределение контроллера Scaffold в Rails 7.1
Контроллер стимулов не загружается
Развертывание Rails завершается с ошибкой «Невозможно загрузить приложение: LoadError: невозможно загрузить такой файл — волокно»
Одна ссылка для изменения одного логического атрибута с false на true без использования формы в Ruby on Rails