BuyProductDialog customization/PostBack issues

For general questions and discussions specific to the AbleCommerce GOLD ASP.Net shopping cart software.
Post Reply
Calbeth
Ensign (ENS)
Ensign (ENS)
Posts: 20
Joined: Thu Oct 04, 2012 8:21 am

BuyProductDialog customization/PostBack issues

Post by Calbeth » Thu Nov 29, 2012 9:05 am

Hi all,

I've been working on customizing BuyProductDialog, as my design comps call for four Customer Fields/product Options to appear in a specific order:

1. TextBox control (integer only; requires custom range validator)
2. DropDownList control (if "Other" is selected, a TextBox appears below)
3. DropDownList control (if "Other" is selected, a TextBox appears below)
4. Textbox (all characters permitted--essentially an "add details" field for customer convenience)

I've basically done two things to achieve this, and my issues are each related to the customizations being "lost" on IsPostBack.

Numer one
Description of customization: First, in BuyProductDialog.ascx, I've created #1 as its own repeater above OptionsList, modeled after TemplatesList. (I'll spare you the gorey details of it but basically, in the codebehind, I've customized GetProductTemplateFields() to handle a passed boolean value, determining whether it's "special" has #1 calls for, or just a regular old Customer Field. So TemplatesList_ItemDataBound works for separate repeaters.)
Issue: What I'm encountering is that while the whole repeater functions, range validator and all, whenever PostBack occurs (e.g., Add to Cart) the value is lost. What must I do to store it and pass it to the Cart or Wishlist?

My code:

Code: Select all

<asp:Repeater ID="AttenuationField" runat="server" OnItemDataBound="TemplatesList_ItemDataBound">
			      <itemtemplate>
				    <tr>
					    <th class="rowHeader" >
                            <span class="custLabel"><%#GetUserName(Container.DataItem)%>:<span class="custRequired">*</span></span>
					    </th>
					    <td runat="server">
                            <asp:TextBox runat="server" ID="Attenuation" Text="" AutoPostBack="false" EnableViewState="true" />
                            <asp:Label ID="AttenuationUnit" runat="server" Text="dB" />
                            <!-- CUSTOM: Validates attenuation range based on admin parameters -->
                            <asp:RangeValidator ID="AttenuationValidator" runat="server" validationgroup="AddToBasket"
                              ControlToValidate="Attenuation" Type="Integer" autopostback="true" Text="*<br />"
                              MinimumValue="<%#GetAttMin()%>" MaximumValue="<%#GetAttMax()%>"
                              ErrorMessage='<%#string.Format("Please enter an attenuation<br />value between {0} and {1}.", GetAttMin(), GetAttMax())%>' />
					    </td>
				    </tr>
			      </itemtemplate>
			    </asp:Repeater>
Number two
Description of customization: As mentioned a TextBox control must appear if user selects "Other" from an OptionsList dropdrown. So within the OptionsList repeater below the last </tr>, I've added a custom HTML control:

Code: Select all

<tr>
                    	<th class='rowHeader'>&nbsp;</th>
                        <td runat="server">
                           <input id="<%#GetOtherField(Container.DataItem, 1)%>" name="<%#GetOtherField(Container.DataItem, 1)%>" value="<%#GetOtherField(Container.DataItem, 2)%>" onfocus="<%#GetOtherField(Container.DataItem, 3)%>" onblur="<%#GetOtherField(Container.DataItem, 4)%>" style="display:none"/>
                        </td>
                    </tr>
(Where "GetOtherField" is a void function that creates a unique identity for the HTML input and assigns its properties. This ensures the TextBox is named such that it's related to its respective DropDownList.) Note that I can't use an ASP control or add "runat=server" because I needed the Id to be assigned programmatically for this work. Also note that the show/hide behavior happens client-side, using javascript.
Issue: Again, on PostBack, even if "other" is selected in the DropDownList, the TextBox returns to "display:none" and any values entered are lost. How do I retain these two properties -- text and style -- over the PostBack hump?

Thanks for your help.
Cal

User avatar
david-ebt
Captain (CAPT)
Captain (CAPT)
Posts: 253
Joined: Fri Dec 31, 2010 10:12 am

Re: BuyProductDialog customization/PostBack issues

Post by david-ebt » Thu Nov 29, 2012 9:48 am

Cal,

One thing we've done to communicate between client-side and server-side is to use some hidden fields. By putting a hidden field on the page like this:

Code: Select all

<asp:HiddenField ID="SavedReportsState" runat="server" Value="1" />
We can access that value from within the client-side JavaScript using this jQuery function:

Code: Select all

jQuery.expr[":"].asp = function (a, i, m) {
    return !!(id = jQuery(a).attr('id')) && id.match(m[3] + "$") == m[3];
};
The client side JavaScript to get the value of the hidden field is:

Code: Select all

var reportState = $(":asp(SavedReportsState)").val();
The client side JavaScript to set the value of the hidden field is:

Code: Select all

$(":asp(SavedReportsState)").val("0");
You can also retrieve or set the value of the hidden field in your code behind.

We found the jQuery function at this site:

http://stackoverflow.com/questions/7482 ... asp-object

The jQuery function matches the end of the .NET control ID since .NET will put a bunch of other stuff in front of that for the actual control ID. That does mean you need to be a little careful creating IDs for the controls. You'll need to make sure no other controls end with the same name.

Maybe others have found better ways to do this, but this does do the job.
David
http://www.ecombuildertoday.com
Enhanced Reporting for AbleCommerce
Image

pluggedin
Ensign (ENS)
Ensign (ENS)
Posts: 15
Joined: Sat Jan 19, 2013 5:02 pm

Re: BuyProductDialog customization/PostBack issues

Post by pluggedin » Thu Jan 24, 2013 12:50 pm

Hi Calbeth

I came across your post, and it looks similar to something I am attempting. Just to keep it simple, I am trying to add a Textbox to the buyproduct control to capture a piece of data that can be saved with the cart and re-displays when you go from the cart back to the buyproduct page. I set up a Textbox as a part of the product template in Admin, but found the data does not redisplay, as I believe you discovered as well. However, some things like GetUserName in your forum posting are not defined, and are possibly in custom code that are part of your actual implementation.

Would welcome any pointers you could provide.

User avatar
mazhar
Master Yoda
Master Yoda
Posts: 5084
Joined: Wed Jul 09, 2008 8:21 am
Contact:

Re: BuyProductDialog customization/PostBack issues

Post by mazhar » Fri Jan 25, 2013 5:51 am

pluggedin wrote:Hi Calbeth

I came across your post, and it looks similar to something I am attempting. Just to keep it simple, I am trying to add a Textbox to the buyproduct control to capture a piece of data that can be saved with the cart and re-displays when you go from the cart back to the buyproduct page. I set up a Textbox as a part of the product template in Admin, but found the data does not redisplay, as I believe you discovered as well. However, some things like GetUserName in your forum posting are not defined, and are possibly in custom code that are part of your actual implementation.

Would welcome any pointers you could provide.
You are using the right approch. In order to collect custom input product templates are easy way. I think when prefilling the customer selection on product details page for an item we are missing the code for prodcut templates. You can fix it by first locating following method in Conlib/BuyProductDialog.ascx.cs

Code: Select all

protected void TemplatesList_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            PlaceHolder phControl = e.Item.FindControl("phControl") as PlaceHolder;
            if (phControl != null)
            {
                InputField input = e.Item.DataItem as InputField;
                if (input != null)
                {
                    WebControl o = input.GetControl();
                    if (o != null)
                    {
                        phControl.Controls.Add(o);
                    }
                }
            }
        }
and POST update it like
POST UPDATED

Code: Select all

private BasketItem _Item = null;
protected void TemplatesList_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (_Item == null && !string.IsNullOrEmpty(Request.QueryString["ItemId"]))
            {
                _Item = BasketItemDataSource.Load(AlwaysConvert.ToInt(Request.QueryString["ItemId"]))
            }
            PlaceHolder phControl = e.Item.FindControl("phControl") as PlaceHolder;
            if (phControl != null)
            {
                InputField input = e.Item.DataItem as InputField;
                if (input != null)
                {
                    WebControl o = input.GetControl();
                    if (o != null)
                    {
                        if (_Item != null && _Item.Inputs.Count > 0)
                        {
                            foreach (BasketItemInput biInput in _Item.Inputs)
                            {
                                if (biInput.InputFieldId == input.Id)
                                {   
                                    switch(input.InputType)
                                    {
                                        case InputType.TextBox:
                                            ((TextBox)o).Text = biInput.InputValue;
                                            break;
                                        case InputType.TextArea:
                                            ((TextBox)o).Text = biInput.InputValue;
                                            break;
                                        case InputType.Label:
                                            ((Label)o).Text = biInput.InputValue;
                                            break;

                                        case InputType.DropDownListBox:
                                        case InputType.CheckBoxList:
                                        case InputType.ListBox:
                                            ListItem li = ((ListControl)o).Items.FindByValue(biInput.InputValue);
                                            if (li != null)
                                            {
                                                ((ListControl)o).ClearSelection();
                                                li.Selected = true;
                                            }
                                            break;
                                        case InputType.MultipleListBox:
                                            string[] values = biInput.InputValue.Split(',');
                                            if (values != null)
                                            {
                                                ((ListControl)o).ClearSelection();
                                                foreach (string value in values)
                                                {
                                                    li = ((ListControl)o).Items.FindByValue(value);
                                                    if (li != null)
                                                        li.Selected = true;
                                                }
                                            }
                                            break;
                                    }
                                }
                            }
                        }

                        phControl.Controls.Add(o);
                    }
                }
            }
        }
After saving the file you need to make one more change and that you need to pass BasketItemId in query string like ItemId=n where n is the basket item id . Now simply update the location where you are listing basket items for example Basket page and when setting Product page URL add query string parameter ItemId in it having BasketItemId value. This way product details page will be able to access the product template values already entered by customer and will load the customer fields.

pluggedin
Ensign (ENS)
Ensign (ENS)
Posts: 15
Joined: Sat Jan 19, 2013 5:02 pm

Re: BuyProductDialog customization/PostBack issues

Post by pluggedin » Sat Jan 26, 2013 10:33 am

Mazhar,
Thanks very much for the help. I replaced the code.
This part is coming up with "_Item does not existing in the current context" in this segment

if ( _Item != null && _Item.Inputs.Count > 0)

{
foreach (BasketItemInput biInput in _Item.Inputs)

So I am scratching with what is missing.

User avatar
mazhar
Master Yoda
Master Yoda
Posts: 5084
Joined: Wed Jul 09, 2008 8:21 am
Contact:

Re: BuyProductDialog customization/PostBack issues

Post by mazhar » Mon Jan 28, 2013 3:59 am

oops! I just made some updates to above post. see the updated code block and comments about passing basket item id in query string.

pluggedin
Ensign (ENS)
Ensign (ENS)
Posts: 15
Joined: Sat Jan 19, 2013 5:02 pm

Re: BuyProductDialog customization/PostBack issues

Post by pluggedin » Mon Jan 28, 2013 3:53 pm

Hi Mazhar,

Many thanks for your update! I plugged it in and while it removed the compile error, the saved template Texbox values do not fill in when you jump back from a saved cart or wishlist to item (all the kit component selections do, however).

I put the debug on and _Item is null but the !string.... is always false

so the following code is not hit:

_Item = BasketItemDataSource.Load(AlwaysConvert.ToInt(Request.QueryString["ItemId"]))

and I am not sure what belongs in the "ItemId" to force BasketItemDataSource to load _Item
I've looked endlessly at the documentation and what shows up in debug, but I am spinning my wheels and really need your help again

Best regards

Post Reply