Page 1 of 1

BuyProductDialog customization/PostBack issues

Posted: Thu Nov 29, 2012 9:05 am
by Calbeth
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

Re: BuyProductDialog customization/PostBack issues

Posted: Thu Nov 29, 2012 9:48 am
by david-ebt
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.

Re: BuyProductDialog customization/PostBack issues

Posted: Thu Jan 24, 2013 12:50 pm
by pluggedin
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.

Re: BuyProductDialog customization/PostBack issues

Posted: Fri Jan 25, 2013 5:51 am
by mazhar
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.

Re: BuyProductDialog customization/PostBack issues

Posted: Sat Jan 26, 2013 10:33 am
by pluggedin
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.

Re: BuyProductDialog customization/PostBack issues

Posted: Mon Jan 28, 2013 3:59 am
by mazhar
oops! I just made some updates to above post. see the updated code block and comments about passing basket item id in query string.

Re: BuyProductDialog customization/PostBack issues

Posted: Mon Jan 28, 2013 3:53 pm
by pluggedin
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