formly-js / angular-formly

JavaScript powered forms for AngularJS
http://docs.angular-formly.com
MIT License
2.22k stars 405 forks source link

Provide commonly used integrations and validators with Formly as re-usable extensions #601

Closed slavafomin closed 8 years ago

slavafomin commented 8 years ago

Hello there!

First of all, thank you for this great module and your precious time. I've been studying it for couple of days now, trying to integrate it into our new project and our work-process as well. Some issues aside, it's all going smoothly, the library looks very thought-through and flexible enough.

I've looked into "Matching Two Fields" example and immediately realized it's complexity. I think this functionality is very common to the most applications in the field and the community will greatly benefit if it was provided out-of-the-box without the need to completely understand the example and to implement it in every project manually.

Have you considered to encapsulate such common behavior in the Formly itself or to provide a set of re-usable modules that can be easily loaded into any project? I think it would be a great step forward for this project, i.e. catalogue of re-usable extensions like integration and validation modules.

I'm sorry, I'm absolutely new to the Formly and I can only contribute conceptual ideas at this point. However, I see a great potential in it. I hope in the future I will be able to contribute the code and implementation ideas as well.

Does it make sense? ) Thank you!

kentcdodds commented 8 years ago

Yes, this is totally possible and the way it should be done is with plugins of which there are several. I'm pretty confident that for the most part angular-formly is "done." Any other functionality needed can/should probably be added via a plugin.

Feel free to create a plugin yourself. It should be quite straightforward. For example, the Matching Two Fields example you reference could be made a plugin with a single file that does this:

angular
  .module('angular-formly-match-field', [])
  .config(function config(formlyConfigProvider) {
    // set templates here
    formlyConfigProvider.setType({
      name: 'matchField',
      defaultOptions: function matchFieldDefaultOptions(options) {
        return {
          extras: {
            validateOnModelChange: true
          },
          expressionProperties: {
            'templateOptions.disabled': function(viewValue, modelValue, scope) {
              var matchField = find(scope.fields, 'key', options.data.fieldToMatch);
              if (!matchField) {
                throw new Error('Could not find a field for the key ' + options.data.fieldToMatch);
              }
              var model = options.data.modelToMatch || scope.model;
              var originalValue = model[options.data.fieldToMatch];
              var invalidOriginal = matchField.formControl && matchField.formControl.$invalid;
              return !originalValue || invalidOriginal;
            }
          },
          validators: {
            fieldMatch: {
              expression: function(viewValue, modelValue, fieldScope) {
                var value = modelValue || viewValue;
                var model = options.data.modelToMatch || fieldScope.model;
                return value === model[options.data.fieldToMatch];
              },
              message: options.data.matchFieldMessage || '"Must match"'
            }
          }
        };

        function find(array, prop, value) {
          var foundItem;
          array.some(function(item) {
            if (item[prop] === value) {
              foundItem = item;
            }
            return !!foundItem;
          });
          return foundItem;
        }
      }
    });
  });

If you're interested in creating this plugin, I recommend you check out my egghead.io series: How to Write an Open Source Library and look at the recommendations on the plugins page. Good luck!