json-schema-form / angular-schema-form

Generate forms from a JSON schema, with AngularJS!
https://json-schema-form.github.io/angular-schema-form
MIT License
2.47k stars 653 forks source link

Add the ability to append/prepend the builder list based on decorator/field #784

Open Anthropic opened 7 years ago

Anthropic commented 7 years ago

Enhancement

As a user/developer, when I want to dynamically modify templates I should be able to add builders to fields without the need to modify/customise the actual builder code.

Expected behaviour

I expected to be able to pass a list of fields and the builder with a flag for prepending or appending

Related issues

This stems from issue https://github.com/json-schema-form/angular-schema-form/issues/779#issuecomment-253886014

@json-schema-form/angular-schema-form-lead

kyse commented 7 years ago

Interesting thought. But sounds like you'd need to decorate schema forms builder provider to add logic to conditionally add builders. Or an easier way would be to add a wrapper to each builder from a config method to check the form builder conditions.

angular.module('blah').config(wrapBuilders);

wrapBuilders.$inject = ['schemaFormDecoratorsProvider', 'sfBuilderProvider'];
function wrapBuilders(sfdp, sfbp) {
    var currentDecorator = {};
    angular.forEach(sfdp.decorator(), function wrapDecorator(decorator, name) {
        currentDecorator = { decorator: decorator, name: name };
        if (angular.isFunction(decorator.builder)
            decorator.builder = wrapBuilder(decorator.builder);
        else if (angular.isArray(decorator.builder)
            decorator.builder = decorator.builder.map(function(b) {
                return wrapBuilder(b);
            };
    });

    function wrapBuilder(builder) {
        return function conditionalBuilderWrapper(args) {
            // Apply desired conditions for builders.  Append, Prepend, Pull from setting of array of fields you want, etc.
            // You have access to current.decorator, current.name, builder, sfbp.builders.[buildertype].
            if (your logic) {
                builder(args); // or builder.call(null, args, otherargs) if you need to bind something to its args.
            }
        }
    }
}

I think you can also define builders individually per field's form def?

Anthropic commented 7 years ago

Yes, I was going to re-write some of the decorator/builder process as I don't think the current way decorators operate is flexible enough. For example I have an add-on that does not display and is therefore independent of decorator, but I can't easily provide a single include that says, "load for whatever decorator the person is using" so I need to look at modifying that and at the same time update the builder to handle similar behaviour and optionally not be restricted to decorator so add-ons can be supplied as a single include and so could a builder that needs to attach itself to a list of templates without caring about which decorator it is run within.

kyse commented 7 years ago

Needed this myself today, so here you go.

https://plnkr.co/4xXY7o

Adds two new methods to schemaFormDecoratorsProvider

Disclaimer: not fully tested, so write yourself some test/coverage for it if you use it.

Cheers.