invalidMessage(data, dirty, ignoreCondition, row, options = {}) {
    const { local } = options;
    if (!row) {
      row = getContextualRowData(this.component, data, this.paths);
    }
    if (!ignoreCondition && !this.checkCondition(row, data)) {
      return '';
    }

    // See if this is forced invalid.
    if (this.invalid) {
      return this.invalid;
    }

    // No need to check for errors if there is no input or if it is pristine.
    if (!this.hasInput || (!dirty && this.pristine)) {
      return '';
    }

    const validationScope = { errors: [] };
    processOneSync({
      component: this.component,
      data,
      row,
      local,
      path: this.path || this.component.key,
      parent: this.parent?.component,
      paths: this.paths,
      scope: validationScope,
      instance: this,
      processors: [
        validateProcessInfo
      ]
    });
    const errors = validationScope.errors;
    const interpolatedErrors = FormioUtils.interpolateErrors(this.component, errors, this.t.bind(this));

    return _.map(interpolatedErrors, 'message').join('\n\n');
  }
Returns the invalid message, or empty string if the component is valid.
@param {*} data - The data to check if the component is valid.
@param {boolean} dirty - If the component is dirty.
@param {boolean} ignoreCondition - If conditions for the component should be ignored when checking validity.
@param {*} row - Contextual row data for this component.
@param {*} options - Additional options for validation.
@returns {string} - The message to show when the component is invalid.