I did come up with a very hacky workaround but would still like a “correct” answer from shopify.
Rather than returning an error from buyerJourney.intercept I just manually insert an error banner node and show/hide it myself based on the situation. I still block checkout if its not checked but the error message is all manually controlled. Im a java developer not javascript and this feels extremely hackey so dont judge me on my code below. I cant seem to figure out how to remove the banner by id - it seems like the id is always just the position in the array rather than the id Im setting so Im removing element “2”.
Styling on checkout ui extensions is atrocious (I have to insert empty view node to add padding between consent view and error message, cant change background colors, etc). I hope shopify makes styling less painful in checkout ui extensions - it was 100% customizable on checkout.liquid. Shopify has not offered a replacement now that they are taking away checkout.liquid access to plus customers.
On submit payment it will block and show the error where I want it. On checking the box it will remove the error and add back if I uncheck again. By default the error will not show unless I try to pay or I check then uncheck it.
toml - make sure you enable block_progress option:
[[extensions.targeting]]
module = "./src/Checkout.js"
target = "purchase.checkout.contact.render-after"
[extensions.capabilities]
api_access = true
network_access = true
block_progress = true
extension:
import { extension, Banner, TextField, Button, Checkbox,Form, TextBlock, Style, View } from "@shopify/ui-extensions/checkout";
export default extension("purchase.checkout.contact.render-after", (root, api) => {
const { extension, i18n, shippingAddress, buyerJourney, capabilities } = api;
const consentError = root.createComponent(Banner,
{
status: 'critical',
title:
'Please read and check the consent box before proceeding.',
id: 'consentErrorBanner'
}
);
const view = root.createComponent(View, {
border: 'base',
padding: 'base',
cornerRadius: ['large'],
background: 'subdued',
});
root.appendChild(view);
var consentChecked = "";
const consentCheckbox = root.createComponent(Checkbox, {
checked: false,
onChange: (checkvalue) => {
consentChecked = checkvalue;
console.log("consentChecked:" + consentChecked);
toggleConsentError(root,consentError,consentChecked);
},
},
'please check to consent'
);
view.appendChild(consentCheckbox);
const textConsent = root.createComponent(TextBlock, {appearance: 'warning'},
'In order to purchase this subscription serivce you must read and consent to the legal terms. '
);
view.appendChild(textConsent);
root.appendChild(root.createComponent( View, {border: 'none', padding: 'base'}, ' ', ));
buyerJourney.intercept(
({canBlockProgress}) => {
toggleConsentError(root,consentError,consentChecked);
return consentChecked == true ? {behavior: 'allow'} :{behavior: 'block',reason:'cant proceed without consenting' };
});
});
function toggleConsentError(root,consentError,consentChecked){
if (consentChecked == true){
if (root.children["2"] != null){
root.children["2"].remove();
}
}else{
root.append(consentError);
}
}