How to manually advance to the next shopping cart step

Jerreck McWilliams asked on May 5, 2015 19:45

I need to conditionally skip a step in the shopping cart. Clearly there's an event that causes the steps to progress, but I can't figure out what that event is called or what object it's a member of. Here's what I've tried so far that doesn't work:

protected void Page_Load(object sender, EventArgs e)
{
    if  (true)
    {
        // Tried to increment the current step index
        this.ShoppingCartControl.CurrentStepIndex += 1;

        // Tried calling ButtonNextClickAction() in various ways
        ButtonNextClickAction();
        base.ButtonNextClickAction();
        this.ShoppingCartControl.ButtonNextClickAction();

        // Tried calling LoadStep() which keeps throwing null refs
        this.ShoppingCartControl.LoadStep(this.ShoppingCartControl.CurrentStepIndex++);
        this.ShoppingCartControl.LoadStep(ShoppingCartControl.NextStepIndex);
    }
}

Correct Answer

Jerreck McWilliams answered on May 6, 2015 17:37

Alright, I figured out my problem. I was trying to use members of the ShoppingCart control in the code behind of a ShoppingCartStep control. The ShoppingCart control was not instantiated, and you can't access it from a ShoppingCartStep.

The key to controlling your checkout process is not to modify a step, but to manipulate the parent ShoppingCart control found in CMSModules/Ecommerce/Controls/ShoppingCart/ShoppingCart.ascx.

Specifically, you need to edit the LoadCurrentStep() method in the code behind, which has the following code:

public override void LoadCurrentStep()
{
    if ((CurrentStepIndex >= 0) && (CurrentStepIndex < CheckoutProcessSteps.Count))
    {
        // Shopping cart container
        ShoppingCartContainer = pnlShoppingCart;

        // Default button settings
        ButtonBack.Enabled = true;
        ButtonNext.Enabled = true;
        ButtonBack.Visible = true;
        ButtonNext.Visible = true;
        ButtonBack.Text = GetString("general.back");
        ButtonNext.Text = GetString("general.next");

        if (CurrentStepControl != null)
        {
            // Display checkout process images
            if (DisplayStepImages)
            {
                LoadCheckoutProcessImages();
            }

            // Set shopping cart step container
            CurrentStepControl.StepContainer = pnlCartStepInner;

            // Display current control      
            pnlCartStepInner.Controls.Clear();
            pnlCartStepInner.Controls.Add(CurrentStepControl);
        }
        else
        {
            lblError.Visible = true;
            lblError.Text = GetString("ShoppingCart.ErrorLoadingStep");
        }
    }
}

The important part of this method is where it's clearing controls from the pnlCartStepInner panel and then adding in the next step's control. This is the part you want to modify if you're looking to add logic to your checkout process to control the flow of the process.

For example, I was trying to check the user's cart and skip steps if specific products were not present. Here's some sample code for that:

int productID = 0;
int productCount = 0;

private void CheckProduct()
{
    // Figure out if the product is in the cart
    for (var i = 0; i < ShoppingCartInfoObj.CartItems.Count; i++)
    {
        if (ShoppingCartInfoObj.CartItems[i].SKUID == 530)
        {
            // when we find the product, remember its ID
            productID = i;
        }
        else
        {
            productID = -1;
        }
    }

    // If the product was found, do something.
    // In this case, I was saving it to the session state to use it later
    if (productID != -1)
    {
        productCount = ShoppingCartInfoObj.CartItems[brickID].CartItemUnits;

        Session.Add("ProductCount", productCount);
    }
}

public override void LoadCurrentStep()
{
    if ((CurrentStepIndex >= 0) && (CurrentStepIndex < CheckoutProcessSteps.Count))
    {
        // Shopping cart container
        ShoppingCartContainer = pnlShoppingCart;

        // Default button settings
        ButtonBack.Enabled = true;
        ButtonNext.Enabled = true;
        ButtonBack.Visible = true;
        ButtonNext.Visible = true;
        ButtonBack.Text = GetString("general.back");
        ButtonNext.Text = GetString("general.next");

        if (CurrentStepControl != null)
        {
            // Display checkout process images
            if (DisplayStepImages)
            {
                LoadCheckoutProcessImages();
            }

            // Set shopping cart step container
            CurrentStepControl.StepContainer = pnlCartStepInner;

            //Check if the product exists
            CheckProduct();

            // here's where I change index if the product isn't found
            if(CurrentStepIndex == 3 && productID != -1)
            {
                // increment index
                CurrentStepIndex++;

                // Set this to false so the base ShoppingCart class
                // will update the CurrentStepControl which is a 
                // read-only property.
                mIsControlLoaded = false;
            }

            // Display current control      
            pnlCartStepInner.Controls.Clear();
            pnlCartStepInner.Controls.Add(CurrentStepControl);
        }
        else
        {
            lblError.Visible = true;
            lblError.Text = GetString("ShoppingCart.ErrorLoadingStep");
        }
    }
}
1 votesVote for this answer Unmark Correct answer

Recent Answers


Josef Dvorak answered on May 6, 2015 17:50

Hello Jerreck,

This seems like a correct solution, but if you know for sure you are about to skip a step, you can do so from the code of the previous checkout step as well. Here is an example that always skips a step:

public override void ButtonNextClickAction()
{
    ShoppingCartControl.NextStepIndex = ShoppingCartControl.NextStepIndex + 1;
    base.ButtonNextClickAction();
}

Skipping for previous button works exactly the same, only using the ButtonBackClickAction method.

In the new checkout process model introduced in Kentico 8 it is possible to define a skip action using macro condition.

0 votesVote for this answer Mark as a Correct answer

Jerreck McWilliams answered on May 6, 2015 19:02

Howdy Josef,

Your solution was something we were considering, too. The only problem with it that we noticed was if we ever needed to rearrange our checkout process, or add more logic to it, we would have to move that line of code from step to step. Adding it to the ShoppingCart control lets us have all our logic in one place and that place never changes. Just a design consideration to note for anyone else who stumbles across this.

Looks like yal made this much easier to deal with in Kentico 8, though.

Thanks, Jerreck

0 votesVote for this answer Mark as a Correct answer

   Please, sign in to be able to submit a new answer.