formly-js / angular-formly

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

How to use fieldTransform with promises? #748

Open Devqon opened 6 years ago

Devqon commented 6 years ago

Hi,

In our application we have a requirement for theme-specific fields. In the documentation I found the 'fieldTransform', where you can manipulate the fields before formly compiles them, which seemed like the ideal place for the theme manipulation.

Our theme is loaded by doing a call to obtain a json config file, where the manipulition is defined. The fieldTransform however cannot handle promises, so I have to block the http call before the returning of the fields.

Simple example:

<formly-form fields="fields"></formly-form>

Controller:

$scope.fields = [{
    id: "someId",
    //...
}, {
    id: "someOtherId",
    //..
}];

And the run block:

.run(["formlyConfig", "themeService", (formlyConfig, themeService) => {
    formlyConfig.extras.fieldTransform.push((fields, model, options, form) => {
        while (!themeService.themeConfig) {
            // ugly synchronous waiting...
        }

        var fieldsToManipulate = themeService.themeConfig.fields,
            result = [];

         fields.forEach(f => {
             if (!f.id) {
                 result.push(f);
             } else {
                 let manipulatedField = fieldsToManipulate.find(ftm => {
                     return ftm.id === f.id;
                 });
                 if (!manipulatedField) {
                     result.push(f);
                 } else {
                     if (manipulatedField.disable) {
                         f.templateOptions.disabled = true;
                         result.push(f);
                     } else if (manipulatedField.hide) {
                         // don't add to result
                     }
                 }
             }
         });
         return result;
    });
}]);

How can I make this asynchronous?

egucciar commented 6 years ago

I think this would be better suited for your controller than inside formly conifg. Before setting .fields in your scope, make your ajax call and apply the mutation there. http://jsbin.com/nuyebu/edit?js,output

I think this makes more sense to do in the controller than within formly transform,

Devqon commented 6 years ago

@egucciar I'd agree with that if we had one form, but we have multiple formly-forms in multiple applications, where they all need to have this intercepted functionality.

egucciar commented 6 years ago

I still wouldn't think it's appropriate for fieldTransforms but that's just me. How about an injectable service that can do the mutation and wrap your calls? That way if in any case you do not not require the mutation it is trivial not to have it.

Devqon commented 6 years ago

Another issue is the nesting of fields/fieldgroups. If I am using a service to do the manipulation myself, I'll have to do a recursive check on all sub-fields and -groups.

egucciar commented 6 years ago

That doesn't sound like an issue. I also created a form mutator for my project and believe it's a superior approach from an architecture perspective as this can scale to scenarios where a global configuration object would make it more difficult to use straight formly forms with no mutation applied.