Я работаю над своим первым проектом 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>
После рендеринга страница @total больше не существует. Вам понадобится какой-то JavaScript, чтобы поддерживать динамический промежуточный итог.
@engineersmnky Ах, понятно, ценю это. Тогда я, вероятно, рассмотрю некоторые вещи, связанные с JavaScript. Цените комментарий
Вы думаете об этом наоборот. Обновление переменной экземпляра само по себе бессмысленно, поскольку переменные экземпляра сохраняются только до завершения обработки запроса. Если вы хотите, чтобы произошло что-то значимое, вам нужно, чтобы состояние сохранялось где-то между запросами.





Добавить событие для поля суммы
<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>Это псевдокод, возможно, вам придется его немного отредактировать и выполнить рефакторинг.
Огромное спасибо! Просто любопытно, есть ли лучшее место, где можно найти документацию по таким вещам? Я не уверен, где именно искать эти вещи.
После нескольких отличных ответов здесь и некоторых исследований за последние пару дней, вот как мне удалось добавить динамическую сумму для каждого элемента. Я не уверен, насколько хорош этот метод, но, похоже, он работает нормально.
В форму я добавил эту строку (я использую 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».
Надеюсь, это поможет кому-нибудь еще!
Когда требуется что-то динамичное, я предпочитаю интегрировать какой-нибудь js-компонент реакции/vue/что-нибудь еще, чтобы вы могли поместить всю форму внутри js-компонента.