Adam Bernstein
2017-11-02T00:35:53Z
Hello, on the page ProductViewer I am trying to hide certain options under certain circumstances. We are using Hotcakes version 1.10.4 Pro.

In _ProductDetails.cshtml, I added logic inside the loop foreach (var opt in Model.LocalProduct.Options):

foreach (var opt in Model.LocalProduct.Options)
                {            
                    if (HasStudentOptions(opt) && !ShowStudentPricing())
                    {                
                        RemoveStudentOptions(opt);
                    }
                    <div class="dnnFormItem clearfix">
                        @if (!opt.NameIsHidden)
                        {<label class="dnnLabel">@opt.Name</label>}
                        <div class="hc-option">
                            @Html.Raw(opt.RenderWithSelection(Model.Selections.OptionSelectionList))
                        </div>
                    </div>                    
                }

For RemoveStudentOptions, I tried two approaches:

Approach #1 was to remove the unwanted OptionItems from the actual Items list of the product's option:

private void RemoveStudentOptions(Hotcakes.Commerce.Catalog.Option opt)
	    {
	        int i = 0;
	        foreach(var optItem in opt.Items)
	        {
	            if (!optItem.Name.EndsWith("Student"))
	            {
	                //opt.Items.Remove(optItem);
	                opt.Items.RemoveAt(i);
	            }
	            i += 1;
	        }
	    }

However this caused the product viewer to not render at all, producing the error:
Quote:

InnerMessage:Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'.
InnerStackTrace:
at System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride)
at System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage)
at System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm)
at System.Web.HttpServerUtilityWrapper.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm)
at System.Web.Mvc.Html.ChildActionExtensions.ActionHelper(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues, TextWriter textWriter)
at System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues)
at Hotcakes.Commerce.Dnn.Mvc.MvcRenderingEngine.Render(String controllerName, String actionName, String viewName, Object routeValues)
at Hotcakes.Modules.ProductViewer.ProductViewerView.RenderView()
at Hotcakes.Commerce.Dnn.Web.HotcakesModuleBase.OnLoad(EventArgs e)



Approach #2 was to clone the Items list of the product's option, and render it rather than the original:

private Hotcakes.Commerce.Catalog.Option RemoveStudentOptions(Hotcakes.Commerce.Catalog.Option opt)
    {
        var newOpt = opt.Clone();
        newOpt.Items.Clear();
        foreach(var optItem in opt.Items)
        {
            if (!optItem.Name.EndsWith("Student"))
            {
                newOpt.Items.Add(optItem);
            }
        }
        return newOpt;
    }

This renders the options as desired on the page, however it produces the error "Please make all selections before adding to cart" as shown in the image attached below.

Is there a way to achieve the goal of conditionally hiding certain options?

Thanks in advance,
Adam

Error message for approach 2
Matt Rutledge
2017-11-02T20:49:19Z
Adam the way we do this is to hide the product options with a style of display: none. Then we perform the selection on the hidden options via a javascript callback. For our instance, we know what selection to make based on the users earlier input. In your instance, you can hook up a javascript change event on your second option list that you created in your Attempt #2 to select the option in the hidden primary option list.
Adam Bernstein
2017-11-03T00:03:58Z
Thank you Matt! That approach seems to be working well at first look.

Here is the code I used in _ProductDetails.cshtml (along with approach #2 from my original post).

int optionItemCounter = 0; //Counts optionItems across all options for the product, for use with PracticeWise custom student option hiding code.
                foreach (var opt in Model.LocalProduct.Options)
                {                      
                    string optId = "hccProductOption" + optionItemCounter;
                    string newOptId = "hccNonStudentProductOption" + optionItemCounter;
                    string optDisplay = "Block";
                    if (HasStudentOptions(opt) && !ShowStudentPricing())
                    { //Set display of the original option to none, and display a clone without the student optionItems.
                        optDisplay = "None";
                        Hotcakes.Commerce.Catalog.Option newOpt;
                        newOpt = CloneWithoutStudentOptions(opt);                        
                        <div class="dnnFormItem clearfix" id="@newOptId">
                            @if (!newOpt.NameIsHidden)
                                {<label class="dnnLabel">@newOpt.Name</label>}
                            <div class="hc-option">
                                @Html.Raw(newOpt.RenderWithSelection(Model.Selections.OptionSelectionList))
                            </div>
                        </div>                        
                    }                    
                    <div class="dnnFormItem clearfix" id="@optId" style="display:@optDisplay">
                        @if (!opt.NameIsHidden)
                                {<label class="dnnLabel">@opt.Name</label>}
                        <div class="hc-option">
                            @Html.Raw(opt.RenderWithSelection(Model.Selections.OptionSelectionList))
                        </div>
                    </div>
                    if (HasStudentOptions(opt) && !ShowStudentPricing())
                    { //Add an event listener for the option's clone (newOpt) and use it to update the selection for the original option (opt).
                        <script type="text/javascript">
                            document.getElementById('@newOptId').onclick = function() {
                                var optName = document.getElementById('@optId').getElementsByTagName('input')[0].name;
                                var newOptName = document.getElementById('@newOptId').getElementsByTagName('input')[0].name;
                                var selectdValue = $('input[name="' + newOptName +'"]:checked').val();                                
                                $('input[name="' + optName + '"][value="' + selectdValue + '"]').prop('checked', true);                                                                
                            };
                        </script>
                    }
                }
                optionItemCounter++;
Will Strohl
2017-11-15T02:39:18Z
@Adam: It sounds like you have this resolved. Is that right?
Will Strohl, Upendo Ventures
Hotcakes Cloud  | Get Support  | Code Support 
Official Cloud & Support provider for Hotcakes
Adam Bernstein
2017-11-16T02:22:15Z
Hi Will, thanks for checking on this. Yes, I think this is resolved. I haven't put it into production yet, but it is looking good in my testing.
Loading
  • Sign-up for the Hotcakes Community Newsletter: