Bill Norman
Bill Norman

Reputation: 881

How do you make all textboxes on the form trigger only one event handler?

I have 50 text boxes on this form. They are all for inputting quantities of each item for purchase on our website. Like this:

enter image description here

My intent is to use a TextChanged event or an OnBlur event in the VB CodeBehind to run through and tabulate the values, and keep a running total of the cost.

I am using the <asp:textbox...> format, not the <input type="text"...> format.

I expect it would be some method of adding an event handler that points to the sub that runs the calculations, but it seems like I can't nail down the proper code.

The specific process, thus far, is this:

  1. When the page loads, it reads a text file* that contains an array of data that includes a unique designation for each item and that item's price, i.e., " item_001,25 " -- meaning item one is $25.
  2. The codebehind performs a FindControl([Item_001]) to locate the specific label where the price goes, and sets that label with the corresponding price.
  3. This loops until the entire file is read. Then the page is displayed with the prices.

*I did it this way only temporarily. Eventually it will find those prices inside a database table, but I haven't set it up yet.

I would like to use that same loop to identify the text boxes and create an event handler for each of them, all pointing to the same sub. It'd be easier than just adding a list of "handles" clauses to one event handler. What I am seeing in my searches so far has been dynamically creating the text box and adding the handler. But the textbox is already there, I only need to add the handlers.

Is this doable? Or is there a better way?

Upvotes: 1

Views: 691

Answers (2)

Brett Caswell
Brett Caswell

Reputation: 1504

This should be a good little template for you to review.

We're essentially using an XmlHttpRequest object to post data to a generichandler page. The XHR object responds with a status and the responseText.

Form.ProductPage.aspx (Markup)

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Form.ProductPage.aspx.vb" Inherits="TestWebApplication.Form_ProductPage" %>
<!DOCTYPE html>

<html>
<head>
    <title></title>
    <script type="text/javascript">
            var ProductManager = {
                'post': function(data, fnSuccessCallback, fnFailCallback) {
                    var xmlhttp = new XMLHttpRequest();
                    xmlhttp.onreadystatechange = function() {
                        if (xmlhttp.readyState==4 && xmlhttp.status==200){
                            fnSuccessCallback(xmlhttp.responseText);
                        }
                        else {
                            if (!(fnFailCallback == null)) {
                                fnFailCallback();
                            }
                        }
                    }
                    xmlhttp.open("POST","Handler.Products.ashx", true);
                    xmlhttp.send(data);
                },
                'label': null,
                'textbox': null,
                'onBlurHandler':function(e) {
                    e.preventDefault();

                    //update the static datado an ajax post, and update total cost
                    var data = { 
                            'product' : e.target.parentElement.querySelector('span').innerText,
                            'quantity' : e.target.value
                        };

                    ProductManager.post(data, function(result){
                        var elm = document.getElementById('debugWindow');
                        elm.innerHTML += '<br />' + result;
                    });
                },
                'onChangeHandler':function(e) {
                    e.preventDefault();
                },
                'onKeyPressHandler':function(e) {
                    //e.preventDefault();                   
                },
                'init': function() {
                    ProductManager.label = document.querySelectorAll('.product-wrapper>span');
                    ProductManager.textbox = document.querySelectorAll('.product-wrapper>input');
                    for (i = 0; i < ProductManager.textbox.length; i++) {
                        ProductManager.textbox[i].addEventListener('blur', ProductManager.onBlurHandler, false);
                        ProductManager.textbox[i].addEventListener('change', ProductManager.onChangeHandler, false);
                        ProductManager.textbox[i].addEventListener('keypress', ProductManager.onKeyPressHandler, false);
                    }

                }
        }
    </script>
</head>
<body>
    <div id="content-wrapper">
            <div class="product-wrapper">
                <span runat="server" id="lblProduct1Label"></span>
                <input runat="server" type="text" id="tbProduct1Quantity" value="0" /></div>
            <div class="product-wrapper">
                <span runat="server" id="lblProduct2Label"></span>
                <input runat="server" type="text" id="tbProduct2Quantity" value="0" /></div>
            <div class="product-wrapper">
                <span runat="server" id="lblProduct3Label"></span>
                <input runat="server" type="text" id="tbProduct3Quantity" value="0" /></div>
            <div class="product-wrapper">
                <span runat="server" id="lblProduct4Label"></span>
                <input runat="server" type="text" id="tbProduct4Quantity" value="0" /></div>
            <div class="product-wrapper">
                <span runat="server" id="lblProduct5Label"></span>
                <input runat="server" type="text" id="tbProduct5Quantity" value="0" /></div>
            <div class="product-wrapper">
                <span runat="server" id="lblProduct6Label"></span>
                <input runat="server" type="text" id="tbProduct6Quantity" value="0" /></div>
            <div class="product-wrapper">
                <span runat="server" id="lblProduct7Label"></span>
                <input runat="server" type="text" id="tbProduct7Quantity" value="0" /></div>
            <div class="product-wrapper">
                <span runat="server" id="lblProduct8Label"></span>
                <input runat="server" type="text" id="tbProduct8Quantity" value="0" /></div>
            <div class="product-wrapper">
                <span runat="server" id="lblProduct9Label"></span>
                <input runat="server" type="text" id="tbProduct9Quantity" value="0" /></div>
            <div class="product-wrapper">
                <span runat="server" id="lblProduct10Label"></span>
                <input runat="server" type="text" id="tbProduct10Quantity" value="0" /></div>
            <div class="product-wrapper">
                <span runat="server" id="lblProduct11Label"></span>
                <input runat="server" type="text" id="tbProduct11Quantity" value="0" /></div>
            <div class="product-wrapper">
                <span runat="server" id="lblProduct12Label"></span>
                <input runat="server" type="text" id="tbProduct12Quantity" value="0" /></div>
        </div>
        <div id="debugWindow">
        </div>
        <script>
            ProductManager.init();
        </script>
</body>
</html>

Form.ProductPage.aspx.vb (PageBehind)

Public Class Form_ProductPage
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Not IsPostBack Then
            For Each InputControl As HtmlInputText In Me.Controls.OfType(Of HtmlInputText).ToList
                InputControl.Value = "0"
            Next

            Dim I As Integer = 0
            For Each LabelControl As HtmlGenericControl In Me.Controls.OfType(Of HtmlControls.HtmlGenericControl).ToList
                LabelControl.InnerHtml = "Product " & I
                I += 1
            Next
        End If
    End Sub
End Class

Handler.Products.ashx.vb (GenericHandler Page/File)

Imports System.Web
Imports System.Web.Services

Public Class Handler_Products
    Implements System.Web.IHttpHandler

    Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest

        context.Response.ContentType = "text/plain"
        context.Response.Write("Hello World!")

    End Sub

    ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
        Get
            Return False
        End Get
    End Property

End Class

Note: The context exposes the HttpRequest object and HttpResponse object. you'll use these objects to determine

  1. what payload data the request has
    • context.request.form
    • context.request.querystring
    • context.request.requestdata.routedata
    • context.request.cookie
    • context.request.headers
  2. what security the request user has.
    • request.user
  3. how to respond
    • context.request.contenttype
    • context.response.write
    • context.resposne.contenttype

Among other possible validation and handling methods.

This is also a good area to query your database. Log/Update user session/activity details.

Upvotes: 1

user1932634
user1932634

Reputation: 181

I don't write or maintain any web applications.

Based on your question, This is what I envision if I had to write something similar for a desktop app.

Hopefully it will give you some ideas, and best of luck!

Option Strict On
Public Class MyItem
    Public Property ItemID As Integer
    Public Property Value As Decimal
End Class


Public Class Form1
    Private _MyItemList As New List(Of MyItem)

    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()
        '1, Update the tag property for each text box you need to identify on the form

        '2, Instead of using an array. Populate the _MyItemList when you load the file

        '3, Loop through the controls list 
        Me.Controls.OfType(Of TextBox).ToList.ForEach(Sub(_textBox)
                                                          If _textBox.Tag Is Nothing OrElse Not IsNumeric(_textBox.Tag) Then Exit Sub 'stop and loop to the next textbox
                                                          Dim _textboxID As Integer = CInt(_textBox.Tag)

                                                          'I like to get a list so I can check for duplicates
                                                          'You could use Dim _item As MyItem = _MyItemList.SingleOrDefault(Function(item) item.ItemID = _textboxID)
                                                          Dim _item As List(Of MyItem) = _MyItemList.Where(Function(item) item.ItemID = _textboxID).ToList

                                                          'Validate item
                                                          If _item Is Nothing Then Exit Sub 'Or throw an "unable to locate item" exception?
                                                          If _item.Count > 1 Then Throw New Exception("Duplicate items found for ID: " & _item(0).ItemID.ToString)

                                                          'You could add event handlers here
                                                          AddHandler _textBox.TextChanged, AddressOf TextValueChanged
                                                          AddHandler _textBox.KeyUp, AddressOf TextKeyPress

                                                          _textBox.Text = _item(0).Value.ToString 'NOTE: The text changed event will fire. Move this line above the AddHandler if this is not desired

                                                      End Sub)
    End Sub

    Private Sub TextValueChanged(sender As Object, e As EventArgs)
        'do something

    End Sub

    Private Sub TextKeyPress(sender As Object, e As KeyEventArgs)
        'do something
    End Sub
End Class

Upvotes: 0

Related Questions