Esempio n. 1
0
function formlyEval(scope, expression, $modelValue, $viewValue, extraLocals) {
  if (angular.isFunction(expression)) {
    return expression($viewValue, $modelValue, scope, extraLocals);
  } else {
    return scope.$eval(expression, angular.extend({$viewValue, $modelValue}, extraLocals));
  }
}
Esempio n. 2
0
 angular.forEach(checkerObjects, (shape, name) => {
   const checker = instance.shape(shape)
   const checkOptions = angular.extend({
     prefix: `formly-field type ${options.type} for property ${name}`,
     url: formlyApiCheck.config.output.docsBaseUrl + 'formly-field-type-apicheck-failed',
   }, apiCheckOptions)
   instance[fn](checker, options[name], checkOptions)
 })
Esempio n. 3
0
 function extendOptionsWithDefaults(options, index) {
   const key = options.key || index || 0;
   angular.extend(options, {
     // attach the key in case the formly-field directive is used directly
     key,
     value: valueGetterSetter,
     runExpressions,
     resetModel,
     updateInitialValue
   });
 }
Esempio n. 4
0
      function setupOptions() {
        formlyApiCheck.throw(optionsApi, [$scope.options], {prefix: 'formly-form options check'});
        $scope.options = $scope.options || {};
        $scope.options.formState = $scope.options.formState || {};

        angular.extend($scope.options, {
          updateInitialValue,
          resetModel
        });

      }
Esempio n. 5
0
// @ngInject
function formlyUsability(formlyApiCheck, formlyErrorAndWarningsUrlPrefix) {
  angular.extend(this, {
    getFormlyError,
    getFieldError,
    checkWrapper,
    checkWrapperTemplate,
    getErrorMessage,
    $get: () => this,
  })

  function getFieldError(errorInfoSlug, message, field) {
    if (arguments.length < 3) {
      field = message
      message = errorInfoSlug
      errorInfoSlug = null
    }
    return new Error(getErrorMessage(errorInfoSlug, message) + ` Field definition: ${angular.toJson(field)}`)
  }

  function getFormlyError(errorInfoSlug, message) {
    if (!message) {
      message = errorInfoSlug
      errorInfoSlug = null
    }
    return new Error(getErrorMessage(errorInfoSlug, message))
  }

  function getErrorMessage(errorInfoSlug, message) {
    let url = ''
    if (errorInfoSlug !== null) {
      url = `${formlyErrorAndWarningsUrlPrefix}${errorInfoSlug}`
    }
    return `Formly Error: ${message}. ${url}`
  }

  function checkWrapper(wrapper) {
    formlyApiCheck.throw(formlyApiCheck.formlyWrapperType, wrapper, {
      prefix: 'formlyConfig.setWrapper',
      urlSuffix: 'setwrapper-validation-failed',
    })
  }

  function checkWrapperTemplate(template, additionalInfo) {
    const formlyTransclude = '<formly-transclude></formly-transclude>'
    if (template.indexOf(formlyTransclude) === -1) {
      throw getFormlyError(
        `Template wrapper templates must use "${formlyTransclude}" somewhere in them. ` +
        `This one does not have "<formly-transclude></formly-transclude>" in it: ${template}` + '\n' +
        `Additional information: ${JSON.stringify(additionalInfo)}`
      )
    }
  }
}
    function setupOptions() {
      formlyApiCheck.throw(
        [formlyApiCheck.formOptionsApi.optional], [$scope.options], {prefix: 'formly-form options check'}
      )
      $scope.options = $scope.options || {}
      $scope.options.formState = $scope.options.formState || {}

      angular.extend($scope.options, {
        updateInitialValue,
        resetModel,
      })

    }
    function addTemplateOptionsAttrs() {
      if (!options.templateOptions && !options.expressionProperties) {
        // no need to run these if there are no templateOptions or expressionProperties
        return;
      }
      const to = options.templateOptions || {};
      const ep = options.expressionProperties || {};

      let ngModelAttributes = getBuiltInAttributes();

      // extend with the user's specifications winning
      angular.extend(ngModelAttributes, options.ngModelAttrs);

      // Feel free to make this more simple :-)
      angular.forEach(ngModelAttributes, (val, name) => {
        /* eslint complexity:[2, 14] */
        let attrVal;
        let attrName;
        const ref = `options.templateOptions['${name}']`;
        const toVal = to[name];
        const epVal = getEpValue(ep, name);

        const inTo = angular.isDefined(toVal);
        const inEp = angular.isDefined(epVal);
        if (val.value) {
          // I realize this looks backwards, but it's right, trust me...
          attrName = val.value;
          attrVal = name;
        } else if (val.expression && inTo) {
          attrName = val.expression;
          if (angular.isString(to[name])) {
            attrVal = `$eval(${ref})`;
          } else if (angular.isFunction(to[name])) {
            attrVal = `${ref}(model[options.key], options, this, $event)`;
          } else {
            throw new Error(
              `options.templateOptions.${name} must be a string or function: ${JSON.stringify(options)}`
            );
          }
        } else if (val.bound && inEp) {
          attrName = val.bound;
          attrVal = ref;
        } else if ((val.attribute || val.boolean) && inEp) {
          attrName = val.attribute || val.boolean;
          attrVal = `${$interpolate.startSymbol()}${ref}${$interpolate.endSymbol()}`;
        } else if (val.attribute && inTo) {
          attrName = val.attribute;
          attrVal = toVal;
        } else if (val.boolean) {
          if (inTo && !inEp && toVal) {
            attrName = val.boolean;
            attrVal = true;
          } else {
            /* eslint no-empty:0 */
            // empty to illustrate that a boolean will not be added via val.bound
            // if you want it added via val.bound, then put it in expressionProperties
          }
        } else if (val.bound && inTo) {
          attrName = val.bound;
          attrVal = ref;
        }

        if (angular.isDefined(attrName) && angular.isDefined(attrVal)) {
          addIfNotPresent(modelNodes, attrName, attrVal);
        }
      });
    }
Esempio n. 8
0
const typeOptionsDefaultOptions = angular.copy(fieldOptionsApiShape)
typeOptionsDefaultOptions.key = apiCheck.string.optional

const formlyTypeOptions = apiCheck.shape({
  name: apiCheck.string,
  template: apiCheck.shape.ifNot('templateUrl', apiCheck.oneOfType([apiCheck.string, apiCheck.func])).optional,
  templateUrl: apiCheck.shape.ifNot('template', apiCheck.oneOfType([apiCheck.string, apiCheck.func])).optional,
  controller: apiCheck.oneOfType([
    apiCheck.func, apiCheck.string, apiCheck.array,
  ]).optional,
  link: apiCheck.func.optional,
  defaultOptions: apiCheck.oneOfType([
    apiCheck.func, apiCheck.shape(typeOptionsDefaultOptions),
  ]).optional,
  extends: apiCheck.string.optional,
  wrapper: specifyWrapperType.optional,
  data: apiCheck.object.optional,
  apiCheck: apiCheckProperty.optional,
  apiCheckInstance: apiCheckInstanceProperty.optional,
  apiCheckFunction: apiCheckFunctionProperty.optional,
  apiCheckOptions: apiCheck.object.optional,
  overwriteOk: apiCheck.bool.optional,
}).strict

angular.extend(apiCheck, {
  formlyTypeOptions, formlyFieldOptions, formlyExpression, formlyWrapperType, fieldGroup, formOptionsApi,
})

export default apiCheck
Esempio n. 9
0
// @ngInject
function formlyConfig(formlyUsabilityProvider, formlyApiCheck) {

  var typeMap = {};
  var templateWrappersMap = {};
  var defaultWrapperName = 'default';
  var _this = this;
  var getError = formlyUsabilityProvider.getFormlyError;

  angular.extend(this, {
    setType,
    getType,
    setWrapper,
    getWrapper,
    getWrapperByType,
    removeWrapperByName,
    removeWrappersForType,
    disableWarnings: false,
    extras: {
      disableNgModelAttrsManipulator: false,
      ngModelAttrsManipulatorPreferUnbound: false,
      removeChromeAutoComplete: false,
      defaultHideDirective: 'ng-if',
      getFieldId: null
    },
    templateManipulators: {
      preWrapper: [],
      postWrapper: []
    },
    $get: () => this
  });

  function setType(options) {
    if (angular.isArray(options)) {
      angular.forEach(options, setType);
    } else if (angular.isObject(options)) {
      checkType(options);
      if (options.extends) {
        extendTypeOptions(options);
      }
      typeMap[options.name] = options;
    } else {
      throw getError(`You must provide an object or array for setType. You provided: ${JSON.stringify(arguments)}`);
    }
  }

  function checkType(options) {
    formlyApiCheck.throw(formlyApiCheck.formlyTypeOptions, options, {
      prefix: 'formlyConfig.setType',
      url: 'settype-validation-failed'
    });
    if (!options.overwriteOk) {
      checkOverwrite(options.name, typeMap, options, 'types');
    } else {
      options.overwriteOk = undefined;
    }
  }

  function extendTypeOptions(options) {
    const extendsType = getType(options.extends, true, options);
    extendTypeControllerFunction(options, extendsType);
    extendTypeLinkFunction(options, extendsType);
    extendTypeValidateOptionsFunction(options, extendsType);
    extendTypeDefaultOptions(options, extendsType);
    utils.reverseDeepMerge(options, extendsType);
    extendTemplate(options, extendsType);
  }

  function extendTemplate(options, extendsType){
    if(options.template && extendsType.templateUrl){
      delete options.templateUrl;
    } else if(options.templateUrl && extendsType.template){
      delete options.template;
    }
  }

  function extendTypeControllerFunction(options, extendsType) {
    const extendsCtrl = extendsType.controller;
    if (!angular.isDefined(extendsCtrl)) {
      return;
    }
    const optionsCtrl = options.controller;
    if (angular.isDefined(optionsCtrl)) {
      options.controller = function ($scope, $controller) {
        $controller(extendsCtrl, {$scope});
        $controller(optionsCtrl, {$scope});
      };
      options.controller.$inject = ['$scope', '$controller'];
    } else {
      options.controller = extendsCtrl;
    }
  }

  function extendTypeLinkFunction(options, extendsType) {
    const extendsFn = extendsType.link;
    if (!angular.isDefined(extendsFn)) {
      return;
    }
    const optionsFn = options.link;
    if (angular.isDefined(optionsFn)) {
      options.link = function () {
        extendsFn(...arguments);
        optionsFn(...arguments);
      };
    } else {
      options.link = extendsFn;
    }
  }

  function extendTypeValidateOptionsFunction(options, extendsType) {
    const extendsFn = extendsType.validateOptions;
    if (!angular.isDefined(extendsFn)) {
      return;
    }
    const optionsFn = options.validateOptions;
    const originalDefaultOptions = options.defaultOptions;
    if (angular.isDefined(optionsFn)) {
      options.validateOptions = function (opts) {
        optionsFn(opts);
        let mergedOptions = angular.copy(opts);
        let defaultOptions = originalDefaultOptions;
        if (defaultOptions) {
          if (angular.isFunction(defaultOptions)) {
            defaultOptions = defaultOptions(mergedOptions);
          }
          utils.reverseDeepMerge(mergedOptions, defaultOptions);
        }
        extendsFn(mergedOptions);
      };
    } else {
      options.validateOptions = extendsFn;
    }
  }

  function extendTypeDefaultOptions(options, extendsType) {
    const extendsDO = extendsType.defaultOptions;
    if (!angular.isDefined(extendsDO)) {
      return;
    }
    const optionsDO = options.defaultOptions;
    const optionsDOIsFn = angular.isFunction(optionsDO);
    const extendsDOIsFn = angular.isFunction(extendsDO);
    if (extendsDOIsFn) {
      options.defaultOptions = function defaultOptions(opts) {
        const extendsDefaultOptions = extendsDO(opts);
        const mergedDefaultOptions = {};
        utils.reverseDeepMerge(mergedDefaultOptions, opts, extendsDefaultOptions);
        let extenderOptionsDefaultOptions = optionsDO;
        if (optionsDOIsFn) {
          extenderOptionsDefaultOptions = extenderOptionsDefaultOptions(mergedDefaultOptions);
        }
        utils.reverseDeepMerge(extendsDefaultOptions, extenderOptionsDefaultOptions);
        return extendsDefaultOptions;
      };
    } else if (optionsDOIsFn) {
      options.defaultOptions = function defaultOptions(opts) {
        let newDefaultOptions = {};
        utils.reverseDeepMerge(newDefaultOptions, opts, extendsDO);
        return optionsDO(newDefaultOptions);
      };
    }
  }

  function getType(name, throwError, errorContext) {
    if (!name) {
      return undefined;
    }
    var type = typeMap[name];
    if (!type && throwError === true) {
      throw getError(
        `There is no type by the name of "${name}": ${JSON.stringify(errorContext)}`
      );
    } else {
      return type;
    }
  }

  function setWrapper(options, name) {
    if (angular.isArray(options)) {
      return options.map(wrapperOptions => setWrapper(wrapperOptions));
    } else if (angular.isObject(options)) {
      options.types = getOptionsTypes(options);
      options.name = getOptionsName(options, name);
      checkWrapperAPI(options);
      templateWrappersMap[options.name] = options;
      return options;
    } else if (angular.isString(options)) {
      return setWrapper({
        template: options,
        name
      });
    }
  }

  function getOptionsTypes(options) {
    if (angular.isString(options.types)) {
      return [options.types];
    }
    if (!angular.isDefined(options.types)) {
      return [];
    } else {
      return options.types;
    }
  }

  function getOptionsName(options, name) {
    return options.name || name || options.types.join(' ') || defaultWrapperName;
  }

  function checkWrapperAPI(options) {
    formlyUsabilityProvider.checkWrapper(options);
    if (options.template) {
      formlyUsabilityProvider.checkWrapperTemplate(options.template, options);
    }
    if (!options.overwriteOk) {
      checkOverwrite(options.name, templateWrappersMap, options, 'templateWrappers');
    } else {
      delete options.overwriteOk;
    }
    checkWrapperTypes(options);
  }

  function checkWrapperTypes(options) {
    let shouldThrow = !angular.isArray(options.types) || !options.types.every(angular.isString);
    if (shouldThrow) {
      throw getError(`Attempted to create a template wrapper with types that is not a string or an array of strings`);
    }
  }

  function checkOverwrite(property, object, newValue, objectName) {
    if (object.hasOwnProperty(property)) {
      warn([
        `Attempting to overwrite ${property} on ${objectName} which is currently`,
        `${JSON.stringify(object[property])} with ${JSON.stringify(newValue)}`,
        `To supress this warning, specify the property "overwriteOk: true"`
      ].join(' '));
    }
  }

  function getWrapper(name) {
    return templateWrappersMap[name || defaultWrapperName];
  }

  function getWrapperByType(type) {
    /* jshint maxcomplexity:6 */
    var wrappers = [];
    for (var name in templateWrappersMap) {
      if (templateWrappersMap.hasOwnProperty(name)) {
        if (templateWrappersMap[name].types && templateWrappersMap[name].types.indexOf(type) !== -1) {
          wrappers.push(templateWrappersMap[name]);
        }
      }
    }
    return wrappers;
  }

  function removeWrapperByName(name) {
    var wrapper = templateWrappersMap[name];
    delete templateWrappersMap[name];
    return wrapper;
  }

  function removeWrappersForType(type) {
    var wrappers = getWrapperByType(type);
    if (!wrappers) {
      return undefined;
    }
    if (!angular.isArray(wrappers)) {
      return removeWrapperByName(wrappers.name);
    } else {
      wrappers.forEach((wrapper) => removeWrapperByName(wrapper.name));
      return wrappers;
    }
  }


  function warn() {
    if (!_this.disableWarnings) {
      /* eslint no-console:0 */
      console.warn(...arguments);
    }
  }
}
// @ngInject
function formlyConfig(formlyUsabilityProvider, formlyErrorAndWarningsUrlPrefix, formlyApiCheck) {

  const typeMap = {}
  const templateWrappersMap = {}
  const defaultWrapperName = 'default'
  const _this = this
  const getError = formlyUsabilityProvider.getFormlyError

  angular.extend(this, {
    setType,
    getType,
    getTypeHeritage,
    setWrapper,
    getWrapper,
    getWrapperByType,
    removeWrapperByName,
    removeWrappersForType,
    disableWarnings: false,
    extras: {
      disableNgModelAttrsManipulator: false,
      fieldTransform: [],
      ngModelAttrsManipulatorPreferUnbound: false,
      removeChromeAutoComplete: false,
      defaultHideDirective: 'ng-if',
      getFieldId: null,
    },
    templateManipulators: {
      preWrapper: [],
      postWrapper: [],
    },
    $get: () => this,
  })

  function setType(options) {
    if (angular.isArray(options)) {
      const allTypes = []
      angular.forEach(options, item => {
        allTypes.push(setType(item))
      })
      return allTypes
    } else if (angular.isObject(options)) {
      checkType(options)
      if (options.extends) {
        extendTypeOptions(options)
      }
      typeMap[options.name] = options
      return typeMap[options.name]
    } else {
      throw getError(`You must provide an object or array for setType. You provided: ${JSON.stringify(arguments)}`)
    }
  }

  function checkType(options) {
    formlyApiCheck.throw(formlyApiCheck.formlyTypeOptions, options, {
      prefix: 'formlyConfig.setType',
      url: 'settype-validation-failed',
    })
    if (!options.overwriteOk) {
      checkOverwrite(options.name, typeMap, options, 'types')
    } else {
      options.overwriteOk = undefined
    }
  }

  function extendTypeOptions(options) {
    const extendsType = getType(options.extends, true, options)
    extendTypeControllerFunction(options, extendsType)
    extendTypeLinkFunction(options, extendsType)
    extendTypeDefaultOptions(options, extendsType)
    utils.reverseDeepMerge(options, extendsType)
    extendTemplate(options, extendsType)
  }

  function extendTemplate(options, extendsType) {
    if (options.template && extendsType.templateUrl) {
      delete options.templateUrl
    } else if (options.templateUrl && extendsType.template) {
      delete options.template
    }
  }

  function extendTypeControllerFunction(options, extendsType) {
    const extendsCtrl = extendsType.controller
    if (!angular.isDefined(extendsCtrl)) {
      return
    }
    const optionsCtrl = options.controller
    if (angular.isDefined(optionsCtrl)) {
      options.controller = function($scope, $controller) {
        $controller(extendsCtrl, {$scope})
        $controller(optionsCtrl, {$scope})
      }
      options.controller.$inject = ['$scope', '$controller']
    } else {
      options.controller = extendsCtrl
    }
  }

  function extendTypeLinkFunction(options, extendsType) {
    const extendsFn = extendsType.link
    if (!angular.isDefined(extendsFn)) {
      return
    }
    const optionsFn = options.link
    if (angular.isDefined(optionsFn)) {
      options.link = function() {
        extendsFn(...arguments)
        optionsFn(...arguments)
      }
    } else {
      options.link = extendsFn
    }
  }

  function extendTypeDefaultOptions(options, extendsType) {
    const extendsDO = extendsType.defaultOptions
    if (!angular.isDefined(extendsDO)) {
      return
    }
    const optionsDO = options.defaultOptions
    const optionsDOIsFn = angular.isFunction(optionsDO)
    const extendsDOIsFn = angular.isFunction(extendsDO)
    if (extendsDOIsFn) {
      options.defaultOptions = function defaultOptions(opts, scope) {
        const extendsDefaultOptions = extendsDO(opts, scope)
        const mergedDefaultOptions = {}
        utils.reverseDeepMerge(mergedDefaultOptions, opts, extendsDefaultOptions)
        let extenderOptionsDefaultOptions = optionsDO
        if (optionsDOIsFn) {
          extenderOptionsDefaultOptions = extenderOptionsDefaultOptions(mergedDefaultOptions, scope)
        }
        utils.reverseDeepMerge(extendsDefaultOptions, extenderOptionsDefaultOptions)
        return extendsDefaultOptions
      }
    } else if (optionsDOIsFn) {
      options.defaultOptions = function defaultOptions(opts, scope) {
        const newDefaultOptions = {}
        utils.reverseDeepMerge(newDefaultOptions, opts, extendsDO)
        return optionsDO(newDefaultOptions, scope)
      }
    }
  }

  function getType(name, throwError, errorContext) {
    if (!name) {
      return undefined
    }
    const type = typeMap[name]
    if (!type && throwError === true) {
      throw getError(
        `There is no type by the name of "${name}": ${JSON.stringify(errorContext)}`
      )
    } else {
      return type
    }
  }

  function getTypeHeritage(parent) {
    const heritage = []
    let type = parent
    if (angular.isString(type)) {
      type = getType(parent)
    }
    parent = type.extends
    while (parent) {
      type = getType(parent)
      heritage.push(type)
      parent = type.extends
    }
    return heritage
  }


  function setWrapper(options, name) {
    if (angular.isArray(options)) {
      return options.map(wrapperOptions => setWrapper(wrapperOptions))
    } else if (angular.isObject(options)) {
      options.types = getOptionsTypes(options)
      options.name = getOptionsName(options, name)
      checkWrapperAPI(options)
      templateWrappersMap[options.name] = options
      return options
    } else if (angular.isString(options)) {
      return setWrapper({
        template: options,
        name,
      })
    }
  }

  function getOptionsTypes(options) {
    if (angular.isString(options.types)) {
      return [options.types]
    }
    if (!angular.isDefined(options.types)) {
      return []
    } else {
      return options.types
    }
  }

  function getOptionsName(options, name) {
    return options.name || name || options.types.join(' ') || defaultWrapperName
  }

  function checkWrapperAPI(options) {
    formlyUsabilityProvider.checkWrapper(options)
    if (options.template) {
      formlyUsabilityProvider.checkWrapperTemplate(options.template, options)
    }
    if (!options.overwriteOk) {
      checkOverwrite(options.name, templateWrappersMap, options, 'templateWrappers')
    } else {
      delete options.overwriteOk
    }
    checkWrapperTypes(options)
  }

  function checkWrapperTypes(options) {
    const shouldThrow = !angular.isArray(options.types) || !options.types.every(angular.isString)
    if (shouldThrow) {
      throw getError(`Attempted to create a template wrapper with types that is not a string or an array of strings`)
    }
  }

  function checkOverwrite(property, object, newValue, objectName) {
    if (object.hasOwnProperty(property)) {
      warn('overwriting-types-or-wrappers', [
        `Attempting to overwrite ${property} on ${objectName} which is currently`,
        `${JSON.stringify(object[property])} with ${JSON.stringify(newValue)}`,
        `To supress this warning, specify the property "overwriteOk: true"`,
      ].join(' '))
    }
  }

  function getWrapper(name) {
    return templateWrappersMap[name || defaultWrapperName]
  }

  function getWrapperByType(type) {
    /* eslint prefer-const:0 */
    const wrappers = []
    for (let name in templateWrappersMap) {
      if (templateWrappersMap.hasOwnProperty(name)) {
        if (templateWrappersMap[name].types && templateWrappersMap[name].types.indexOf(type) !== -1) {
          wrappers.push(templateWrappersMap[name])
        }
      }
    }
    return wrappers
  }

  function removeWrapperByName(name) {
    const wrapper = templateWrappersMap[name]
    delete templateWrappersMap[name]
    return wrapper
  }

  function removeWrappersForType(type) {
    const wrappers = getWrapperByType(type)
    if (!wrappers) {
      return undefined
    }
    if (!angular.isArray(wrappers)) {
      return removeWrapperByName(wrappers.name)
    } else {
      wrappers.forEach((wrapper) => removeWrapperByName(wrapper.name))
      return wrappers
    }
  }


  function warn() {
    if (!_this.disableWarnings && console.warn) {
      /* eslint no-console:0 */
      const args = Array.prototype.slice.call(arguments)
      const warnInfoSlug = args.shift()
      args.unshift('Formly Warning:')
      args.push(`${formlyErrorAndWarningsUrlPrefix}${warnInfoSlug}`)
      console.warn(...args)
    }
  }
}