player-ui / player

Home Page:https://player-ui.github.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Core: Enable validation controller to refresh potential validations from providers directly

sugarmanz opened this issue · comments

Is your feature request related to a problem? Please describe.

Currently, due to the implementation, the only way to tell the validation controller to get potential validations from providers is to manually re-load validations for a binding:

validationController.updateValidationsForBinding(
  binding,
  'load',
  undefined,
  (existingValidation as any)?.onDismiss // retain existing onDismiss
);

if (trigger === 'load') {
// Get all of the validations from each provider
const possibleValidations = this.getValidationProviders().reduce<
Array<ValidationObjectWithSource>
>(
(vals, provider) => [
...vals,
...(provider.provider
.getValidationsForBinding?.(binding)
?.map((valObj) => ({
...valObj,
[VALIDATION_PROVIDER_NAME_SYMBOL]: provider.source,
})) ?? []),
],
[]
);

This does clear the state of validations for that binding. To maintain state for the new validations, we'll have to update the new bindings based on the currentPhase of the previous validation:

validationController
  .getValidationForBinding(binding)
  ?.update(
    existingValidation.currentPhase,
    false,
    (validationObj) =>
      validationController.validationRunner(
        validationObj,
        binding
      )
  );

Describe the solution you'd like

This requires explicit knowledge of how the validation controller works internally, and uses an indirect mechanism to re-poll the validation providers. At the very least, we should have a direct API for telling the controller to rebuild it's validations for a specific binding, but it might make sense to enable providers to directly update the validations provided by that provider.

This'd be a great black-box API, ensuring relevant operations occur automatically on refresh, but it would recall all the validation providers, which might be inefficient.

// takes into account current phase of existing bindings to re-trigger relevant triggers
validationController.refreshValidationsForBinding(binding);

This is a much more targeted approach, ensuring that we only touch the validations provided by provider-name (this information is maintained in the validation object here), but mutations like this could have some unintended side effects:

validationController.updateProvidedValidationsForBinding(
  'provider-name', 
  binding,
  validationObj, // optional validation obj, maybe the controller would automatically invoke _just_ the `provider-name` provider to get the updated bindings
)

Additional context

More complete example containing logic for how to rebuild validations for a specific binding and update to latest phase to maintain validation state:

// if this binding gets some validation info from our provider
// we need to tell the controller to rebuild validations for this binding
if (provider.getValidationsForBinding(binding)) {
  const existingValidation = validationController.getValidationForBinding(binding);
  validationController.updateValidationsForBinding(
    binding,
    'load',
    undefined, // explicitly undefined so the options will be loaded as the default validation controller options
    (existingValidation as any)?.onDismiss // retain existing onDismiss
  );

  if (
    existingValidation?.currentPhase &&
    existingValidation.currentPhase !== 'load'
  ) {
    // update new validations based on current phase of previous validations
    validationController
      .getValidationForBinding(binding)
      ?.update(
        existingValidation.currentPhase,
        false,
        (validationObj) =>
          validationController.validationRunner(
            validationObj,
            binding
          )
      );
  }
}