Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

customValidator is not provided via NG_VALIDATORS or NG_ASYNC_VALIDATORS #271

Closed
anteburazer opened this issue Feb 10, 2017 · 13 comments
Closed

Comments

@anteburazer
Copy link

I have a problem with custom validators but only when building application for production. The problem is in dynamic-form.service.ts file when code enters in getCustomValidatorFn() function.

I'm using Angular CLI with webpack: v1.0.0-beta.31
Angular v2.4.3

The problem appears when code gets uglified and variable names are renamed. Function getCustomValidatorFn() compares two strings which are not equal because of code uglification and because of that it doesn't find anything in NG_VALIDATORS array.

I hope the code below explains the problem. I put console.log() to output breaking lines of code to understand where the issue is. If it's not clear I will explain more clear.

Right now I'm not able to use the library in production.

getCustomValidatorFn(validatorName: string): ValidatorFn | AsyncValidatorFn | undefined  {

        console.debug(validatorName) // myCustomValidator

        let validatorFn;

        console.log(this.NG_VALIDATORS)
        // Array[1]: 
        //     i(t)
        //       arguments(...)
        //       arguments(caller)
        //       length: 1
        //       name: "i"

        if (this.NG_VALIDATORS) {
            validatorFn = this.NG_VALIDATORS.find(validator => {
                console.log(validatorName); // myCustomValidator
                console.log(validator.name); // i
                console.log( validatorName == validator.name) // false 

                // THIS IS CRITICAL LINE OF CODE WHERE FUNCTION NAME IN "this.NG_VALIDATORS"
                // IS EQUAL TO "i" AND FUNCTION PARAMETER "validatorName" IS EQUAL TO "myCustomValidator"
                return validatorName == validator.name
            });

            console.debug(validatorFn) // undefined
        }

        if (!isDefined(validatorFn) && this.NG_ASYNC_VALIDATORS) {
            validatorFn = this.NG_ASYNC_VALIDATORS.find(asyncValidator => validatorName === asyncValidator.name);
        }

        return validatorFn;
    }

    getValidatorFn(validatorName: string, validatorArgs?: any): ValidatorFn | AsyncValidatorFn | never {

        console.debug( validatorName) // myCustomValidator

        let validatorFn = Validators[validatorName] || this.getCustomValidatorFn(validatorName);

        console.debug(validatorFn) // undefined

        if (!isFunction(validatorFn)) {
            throw new Error(`validator "${validatorName}" is not provided via NG_VALIDATORS or NG_ASYNC_VALIDATORS`);
        }

        return isDefined(validatorArgs) ? validatorFn(validatorArgs) : validatorFn;
    }

Is there any solution to workaround this?

Thanks

@udos86
Copy link
Owner

udos86 commented Feb 10, 2017

@anteburazer There it is, Ante!

You've found the single most weak point of current custom validators implementation.

I've already tried to get my head around this.

Is there any chance that you could exclude certain strings / LoC from mangling / uglifying?

@udos86
Copy link
Owner

udos86 commented Feb 11, 2017

@anteburazer I guess, I've got a solution for you!

You just need to exclude the function name from mangling:

plugins: [
    new webpack.optimize.UglifyJsPlugin({
        mangle: {
            except: ['myValidator']
        }
     })
]

@anteburazer
Copy link
Author

@udos86 thanks for your help.

I'm using Angular CLI and I don't have access to webpack config file. They provide some config file to override webpack configuration but as far as I know there's no option to manipulate with mangling options.

My other problem is that I had to customize the library, because of some extra features I needed, so I included it as a regular module inside the project and not via node modules.
I had to make this decision because I needed it ASAP so unfortunately I'm not in sync with your updates anymore :(

I'm not sure how I can integrate your solution but it's up to me cause I branched from this repository because of custom modifications I had to make.

I really appreciate your help. If you have any idea please let me know, if not I'll have to make some workaround for this.

@anteburazer
Copy link
Author

For all adventurers who wants to include this library as project's local module and not via node_modules this is how to workaround this issue:

  • Don't implement custom validators via NG_VALIDATORS but use Angular injectable service instead and define all custom validator functions there.
@Injectable()
export class ValidationService {
  public numericRequired(formControl: FormControl): {[error: string]:any} {
    return (formControl.value && formControl.value > 0) ? null : { numericRequired: { valid: false } };
  }
}
  • Change getCustomValidatorFn() function inside the dynamic-forms.service.ts file to use validation service from above, instead of NG_VALIDATORS
getCustomValidatorFn(validatorName: string): ValidatorFn | undefined {
    let validatorFn;

    if (validatorName in this.validationService) validatorFn = this.validationService[validatorName];

   return validatorFn;
}

I didn't cover async validators in this case. Maybe I will one day when I see red errors in production :)

Enjoy :)

@udos86
Copy link
Owner

udos86 commented Feb 14, 2017

@anteburazer Great! Thanks for figuring out that workaround!

@kirjai
Copy link

kirjai commented Feb 20, 2017

I too have ran into this problem. However, I didn't fork the repo, i'm using the latest version. Is the only workaround found so far is forking the repo and modifying dynamic-forms.service? :/

@udos86
Copy link
Owner

udos86 commented Feb 20, 2017

@kirjai I'll try to figure out a solution for everyone out there using Angular CLI

@udos86
Copy link
Owner

udos86 commented Feb 20, 2017

@kirjai @anteburazer Good news, everybody! I finally found a fix for this! Have a look at aaff8ec.

However there's one constraint: It only works for NG_VALIDATORS not for ASYNC_VALIDATORS

And please always name your validator function the same as the property of it's return object:

export function customValidator(formControl: FormControl) {
    return {
        customValidator: {valid: formControl.value ? (formControl.value as string).startsWith("abc") : false}
    };
}

@anteburazer
Copy link
Author

@udos86 thanks for help.

I didn't try your solution yet but I saw that Angular CLI supports webpack.config.js now: http://www.dzurico.com/angular-cli-with-the-super-powers/

@kirjai you can also try with Udo's first solution by excluding validator's name from mangling

@udos86
Copy link
Owner

udos86 commented Feb 21, 2017

@anteburazer Alright, thanks for the information!

@udos86 udos86 closed this as completed in aaff8ec Feb 21, 2017
@ellipizle
Copy link

i being pulling my hair over this issue but to no avail

13:12:53.883 ERROR in /var/lib/go-agent/pipelines/sample-Web/node_modules/@ng2-dynamic-forms/core/src/service/dynamic-form.service.ts (108,13): Argument of type 'ValidatorFn' is not assignable to parameter of type 'AsyncValidatorFn'.
13:12:53.883   Type 'ValidationErrors' is not assignable to type 'Promise<ValidationErrors> | Observable<ValidationErrors>'.
13:12:53.883     Type 'ValidationErrors' is not assignable to type 'Observable<ValidationErrors>'.
13:12:53.883       Property '_isScalar' is missing in type 'ValidationErrors'.
13:12:53.883 /var/lib/go-agent/pipelines/sample-Web/node_modules/@ng2-dynamic-forms/core/src/service/dynamic-form.service.ts (145,45): Argument of type 'ValidatorFn[] | AsyncValidatorFn[]' is not assignable to parameter of type 'AsyncValidatorFn[]'.
13:12:53.883   Type 'ValidatorFn[]' is not assignable to type 'AsyncValidatorFn[]'.
13:12:53.883     Type 'ValidatorFn' is not assignable to type 'AsyncValidatorFn'.

i followed all the suggested methods but still not solved

@udos86
Copy link
Owner

udos86 commented Apr 3, 2017

@ellipizle Hi! Did you update to 1.4.0?

@paulsouche
Copy link
Contributor

For anyone on webpack 4

    optimization: {
      minimizer: [
        new UglifyJsPlugin({
          uglifyOptions: {
            compress: false,
            mangle: {
              reserved: ['myValidator'],
            },
          },
        }),
      ],
    },

is the new way to achieve this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants