1

If I change an order's status to "Cancelled" (my custom order status I created), I want to ensure that the CP editors provide a "Cancellation Reason" from a dropdown field in the order. I've set up a custom validator to do this but it doesn't get recognized in Commerce's flash message.

In my plugin, I'm adding a custom rule to Order elements like:

use my\plugin\validators\CancellationReasonValidator;
use craft\events\DefineRulesEvent;
use craft\commerce\elements\Order;
use yii\base\Event;

Event::on(
    Order::class,
    Order::EVENT_DEFINE_RULES,
    static function(DefineRulesEvent $event) {
        /* @var Order $order */
        $event->rules[] = [['cancellationReason'], CancellationReasonValidator::class];
    });

My validator looks like:

use Craft;
use craft\commerce\elements\Order;
use yii\validators\Validator;

class CancellationReasonValidator extends Validator
{
    public function validateAttribute($model, $attribute)
    {
        $cancellationReasonField = $model->$attribute;

        /* @var Order $model */
        if (   $model->isCompleted
            && $model->getOrderStatus()->handle === 'cancelled'
            && ! $cancellationReasonField->value) {

            $this->addError($model, $attribute, Craft::t(
                'site',
                'A cancellation reason is required for {orderNumber}',
                ['orderNumber' => $model->shortNumber]
            ));

        }
    }
}

If I edit an order, change the status to "Cancelled", and click the red update button, the validation works: Cancellation Reason dropdown field is invalid

However, if I do this from the orders listing view, where I try to update an order's status like in the screenshot below, there is no flash message displayed to the user that the order couldn't save.

No error message displays after updating order with cancelled status message

I understand there's a lot of asynchronous JS happening here, but how do I tap into showing some sort of message to my CP editors, preferably one that mentions the order's shortNumber?

Add error flash message at top of page

1

I haven't tried this yet, but I think you can try to use "Server Side Event" with "Control Panel JS plugin for Craft CMS": https://github.com/doublesecretagency/craft-cpjs/blob/v2/README.md

Listen to server and append a custom alert when some event triggered at server side.

Here is some information about SSE.

W3S: https://www.w3schools.com/html/html5_serversentevents.asp

SSE Browser Support: https://caniuse.com/#search=Server%20Side%20Event

SSE Polyfill to Support Mobile Android and IE8+ https://github.com/Yaffle/EventSource

Yii2 SSE Server Side Example: https://www.yiiframework.com/wiki/329/real-time-display-of-server-push-data-using-server-sent-events-sse

Yii2 SSE component: https://github.com/odannyc/yii2-sse

Hope this helps.

1

According to this answer from Robin, you can use Craft::$app->session->setError($message); to show that flash error message you're looking for...

2
  • 1
    The issue with "Craft::$app->session->setError($message)" is it only will show one error message in the end. For example, if you used beforeSaveElement event and setError message to something there. The message will likely get overwrite by any other Craft::$app->session->setError($message) called after you. And its often craft's default error message wins. And Ryan is trying to set error message at asynchronous JS interface, "Craft::$app->session->setError($message)" will not work here. – Parry Huang Jun 7 '20 at 4:02
  • @jalen, I set the error flash message but you don't see it until you refresh or change the page. – Ryan Jun 7 '20 at 17:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.