У меня есть строки кода ниже в элементе управления представлением asp:list: если пользователь вводит какое-либо значение во 2-е текстовое поле, на стороне клиента событие потери фокуса мне нужно вычислить txtTokensReq * txtQty и отобразить в lblTotalTokens.
<asp:ListView runat = "server" ID = "lstView" ClientIDMode = "Static" GroupItemCount = "1" OnItemDataBound = "lstView_ItemDataBound">
<asp:TextBox runat = "server" CssClass = "inputQty" MaxLength = "5" ID = "txtTokensReq" ClientIDMode = "Static" Text='<%# Eval("PartToken")%>' ReadOnly = "true"></asp:TextBox>
<asp:TextBox runat = "server" cssClass = "inputQty" MaxLength = "5" ID = "txtQty" Text='<%# Eval("Qty")%>' onKeypress = "if (!validatenumeric(this,5)){return false;}"></asp:TextBox>
<asp:Label ID = "lblTotalTokens" CssClass = "note-maxqty col-last" Text='<%# Eval("TotalTokenReq")%>' runat = "server"></asp:Label>
</asp:ListView>
КОГДА я написал функцию onblur во втором текстовом поле, она срабатывает более одного раза.
Заранее спасибо.
Это мой JS-код, который срабатывает несколько раз (обычно, если есть 5 строк, он срабатывает 5 раз) ``` functioncalcTokensRequired(control) { alert(control.value); вернуть ложь; } ``` <asp:TextBox runat = "server" cssClass = "inputQty" MaxLength = "5" ID = "txtQty" Text='<%# Eval("Qty")%>' onblur = "calcTokensRequired(this);" onKeypress = "if (!validatenumeric(this,5)){return false;}"></asp:TextBox>



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Хорошо, несколько вещей.
Внутри представления списка нет смысла устанавливать идентификатор клиента mode = «static», поскольку элементы управления будут повторяться снова и снова. Таким образом, если вы используете статический идентификатор, мы нарушаем правила HTML, и использование нескольких элементов управления с одним и тем же идентификатором не допускается.
Элементы управления в ListView будут автоматически генерироваться для каждой строки и выглядеть следующим образом:
ListView1_Qty_0
ListView1_Qty_1
ListView1_Qty_2
. etc. for each new row
И, конечно же, если мы хотим использовать селектор для других элементов управления в этой ОДНОЙ строке данных, то нам снова нужно будет выбрать каждый элемент управления на основе вышеизложенного («Имя ListView» + «» + Имя элемента управления + «» + Номер строки.
Вышеупомянутое может быть трудным, поэтому я предпочитаю создавать функцию JavaScript, и мы просто передаем тот «базовый» идентификатор элемента управления, который был в первую очередь.
И неясно, почему вы используете onkey down, вам следует использовать событие onchange, поскольку оно срабатывает только после того, как пользователь выходит из элемента управления (или теряет фокус).
Итак, с этой разметкой:
<div style = "width: 50%" id = "myGridList">
<asp:ListView ID = "ListView1" runat = "server" DataKeyNames = "ID">
<ItemTemplate>
<tr>
<td>
<asp:TextBox ID = "txtFirst" runat = "server" Text='<%# Eval("FirstName") %>' Width = "70px" /></td>
<td>
<asp:TextBox ID = "txtLast" runat = "server" Text='<%# Eval("LastName") %>' Width = "70px" /></td>
<td>
<asp:TextBox ID = "txtCity" runat = "server" Text='<%# Eval("City") %>' Width = "70px" /></td>
<td>
<asp:TextBox ID = "txtHotelName" runat = "server" Text='<%# Eval("HotelName") %>' Width = "100px" /></td>
<td>
<asp:TextBox ID = "txtDescription" runat = "server" Text='<%# Eval("Description") %>'
TextMode = "MultiLine" Columns = "52" />
</td>
<td style = "text-align: right">
<asp:TextBox ID = "txtNights" runat = "server" Text='<%# Eval("Nights") %>' Width = "35px"
onchange = "jcalc(this,'txtNights')" />
</td>
<td style = "text-align: center">
<asp:TextBox ID = "txtPerNight" runat = "server" Text='<%# Eval("NightRate", "{0:C0}") %>' Width = "40px"
onchange = "jcalc(this,'txtPerNight')" />
</td>
<td style = "text-align: right">
<asp:Label ID = "txtPrice" runat = "server"
Text='<%# Eval("Price", "{0:C2}") %>' />
</td>
<td style = "text-align: center">
<button id = "cmdDelete" runat = "server" class = "btn"
onserverclick = "cmdDelete_ServerClick" tabindex = "-1"
onclick = "if (!confirm('Really delete')) {return false}">
<span aria-hidden = "true" class = "glyphicon glyphicon-trash"></span>
</button>
</td>
</tr>
</ItemTemplate>
<LayoutTemplate>
<table id = "itemPlaceholderContainer" runat = "server"
class = "table table-hover table-bordered table-striped borderhide">
<tbody>
<tr runat = "server" style = "">
<th runat = "server" style = "width: 60px">First</th>
<th runat = "server" style = "width: 60px">Last</th>
<th runat = "server" style = "width: 60px">City</th>
<th runat = "server" style = "width: 70px">Hotel Name</th>
<th runat = "server" style = "width: 140px">Description</th>
<th runat = "server" style = "width: 60px">Nights</th>
<th runat = "server" style = "width: 60px">Per<br />
Night</th>
<th runat = "server" style = "width: 60px">Amount</th>
<th runat = "server" style = "width: 60px"></th>
</tr>
<tr id = "itemPlaceholder" runat = "server">
</tr>
</tbody>
<tfoot>
<tr>
<%-- skip 6 boxes --%>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td style = "text-align: right">Total</td>
<td style = "text-align: right">
<asp:Label ID = "lblTotalSum" runat = "server" Width = "62px" ClientIDMode = "Static">
</asp:Label>
</td>
</tr>
</tfoot>
</table>
</LayoutTemplate>
</asp:ListView>
</div>
<button id = "cmdSave" runat = "server" class = "btn"
onserverclick = "cmdSave_Click" tabindex = "-1">
<span aria-hidden = "true" class = "glyphicon glyphicon-share">Save / Update</span>
</button>
<button id = "cmdAddNew3" runat = "server" class = "btn" style = "margin-left: 20px"
onserverclick = "cmdAddNew_Click" tabindex = "-1">
<span aria-hidden = "true" class = "glyphicon glyphicon-plus-sign">New Hotel</span>
</button>
<button id = "cmdUnDo" runat = "server" class = "btn" style = "margin-left: 20px"
onserverclick = "cmdUnDo_ServerClick" tabindex = "-1">
<span aria-hidden = "true" class = "glyphicon glyphicon-retweet">Undo</span>
</button>
</div>
<script>
function jcalc(ctl, tid) {
// simple grid update price from nights X rate
var Nights = $('#' + ctl.id.replace(tid, 'txtNights'))
var Price = $('#' + ctl.id.replace(tid, 'txtPerNight'))
var tAmount = $('#' + ctl.id.replace(tid, 'txtPrice'))
var MyPrice = Nights.val() * DollarToNum(Price.val())
tAmount.text(NumToDollar(MyPrice))
// change save button to blue - shows edits were done
$('#cmdSave').addClass('btn btn-info')
// total up colum for display
var myGrid = $("#myGridList") // select list view area (div)
myTotalcols = myGrid.find("[id *= txtPrice]") // select txtPrice from list view
var myTotal = 0;
myTotalcols.each(function () {
myvalue = DollarToNum(this.innerText)
myTotal += myvalue});
$('#lblTotalSum').text(NumToDollar(myTotal)) // control in footer
}
function DollarToNum(sValue) {
// take sring currency such as $12,555,00 and conver to number
return Number(sValue.replace(/[^0-9.-]+/g, ""))
}
function NumToDollar(sValue) {
// take number and convert to string with currency format
var dollarUSLocale = Intl.NumberFormat('en-US',
{ style: "currency", currency: "USD", useGrouping: true, minimumFractionDigits: 2 })
var resultamount = 0
return dollarUSLocale.format(sValue)
}
</script>
Обратите внимание, как я обернул ListView в div с идентификатором, поэтому я выбираю его на странице. (в конце концов, на странице может быть более одного ListView).
Обратите внимание, как я просто передаю «базовый» идентификатор элемента управления с помощью функции JavaScript. Поскольку для каждой строки существует процесс именования «строки», я просто заменяю текст нужных мне значений на основе идентификатора текущего элемента управления (который будет включать номер этой строки и имя элемента управления).
Я также показываю, как можно выбрать каждую строку с помощью селектора jQuery с подстановочным знаком, и я использовал его для суммирования полученных значений и размещения их в элементе управления нижнего колонтитула.
Итак, результат выглядит так:
Итак, я предлагаю удалить ClientIDMode для элементов управления в ListView, поскольку они будут повторяться, и вы потеряете практические возможности выбора элементов управления из заданной строки.
Спасибо за ваш ответ, я не думаю, что смогу удалить ClientIDMode из списка, поскольку у меня уже реализована функция сохранения, как показано ниже.
Я не могу удалить ClientIDMode, поскольку у меня реализована функция сохранения, как показано ниже ``` function buttonLstSaveHandler() { var allItems = $(".qtyBox"); // <div class = "qtyBox"> над элементом управления списком for (var i = 0; i < allItems.length; i++) //logic } if (valid && arCartItems.length > 0) { var params = { partCategoryID: partCategoryID , lstCartItem: arCartItems }; callWebService('SaveCartItems', params, false, true, ajaxFailureHandlerCartSave, функция (данные) {}); } } ```
Посмотрите на мой код, чтобы выбрать все общие значения. Я использовал «[id *= txtPrice]», или вы можете использовать *=Qty. Я имею в виду, я полагаю, вы могли бы использовать first или close в селекторе запроса, но, как показывает приведенный выше код, это простой и приятный способ выбрать элементы управления из заданной строки с помощью замены. Итак, в приведенном выше примере я выбрал все txtPrice и суммировал их из этого GridView. А поскольку вы используете «.», то это означает выбор по классу для этого элемента управления, и, следовательно, то, что у вас есть, также должно работать нормально, чтобы выбрать все, но без идентификаторов строк, тогда ваш выбор может легко испортиться. Я предлагаю подход замены.
Спасибо, можно ли прочитать несколько столбцов, используя приведенные ниже строки кода? ``` var myGrid = $("#myGridList") // выбор области просмотра списка (div) myTotalcols = myGrid.find("[id *= txtPrice]") var myTotal = 0; myTotalcols.each(function () { myvalue = DollarToNum(this.innerText) myTotal += myvalue }); } ``` Мне нужно вычислить токен qty * для каждой строки, и мне нужен partid при сохранении, как показано ниже ``` arCartItems.push({ "PartID": partID, "Qty": количество }); ```
Ну а если ВСЕГДА делать расчет для одной строки, то таблица всегда должна быть верной, не так ли? То есть таблица отправляется + рендерится с сервера с правильными вычислениями. И мой приведенный выше код выполняет вычисления для одной строки, поэтому теоретически не должно быть возможности иметь неправильную таблицу, поскольку каждая строка всегда сохраняется правильной, если мы запускаем вычисления для одной строки. Если вам нужно общее количество столбцов, нам ВСЕ ЕЩЕ не нужно заново выполнять вычисления, поскольку мы можем предположить, что одна строка ВСЕГДА верна. Наверняка у вас может быть несколько столбцов для суммирования.
Привет, Альберт! Спасибо за вашу помощь, я удалил ClientIDMode = "Static" на уровне Listview и добавил ClientIDMode = "Predictable" в несколько столбцов, которые я хочу прочитать на стороне клиента.
Не беспокойся. Эту «хитрость» с использованием замены по-прежнему очень удобно держать в запасе. Итак, если пятая строка, скажем, ListView1_Qty_4 и, скажем, ListView1_Price_4, тогда мы можем заменить Qty на «Цена», и у нас будет действительный селектор jQuery для этого одного элемента управления в этой строке LV.
Можете ли вы поделиться своим кодом с кодом проблемы.