@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
103 lines • 12.9 kB
JavaScript
import { FormControl } from '@angular/forms';
import { forkJoin, of } from 'rxjs';
import { map } from 'rxjs/operators';
export const ARRAY_VALIDATION_PREFIX = 'INNER_ARRAY_ERROR_';
/**
* This method can alter how validators work. It can be used in cases where there is need to validate FormControl
* that as value, takes array of elements. This allows to reuse validators, that works for such elements.
* For example if Validators.minLength(3) is used on control that takes string as value, validator will return error
* if string is less than 3 characters. If same is done on array of strings, validator will return error if array
* has less than 3 elements.
*
* validateArrayElements(Validators.minLength(3)) method makes it possible to check every member of array if it has minimum 3 characters.
* If there are elements that raise error, it will be possible to extract these errors using item index.
*
* As a example, this can be used for custom form elements, which manipulates array of elements,
* and there is need to display corresponding error messages for every array member that is displayed, while still using
* Angular's Validation approach.
*
* Errors that are generated by this helper are prefixed with 'INNER_ARRAY_ERROR_'. Reason for this is to prevent overwriting normal validation
* errors that could have same key
*
* @Example
*
* let control = new FormControl(['1234', '123456', '123', [Validators.minLength(5), validateArrayElements(Validators.minLength(5))] ])
*
* this FormControl has validation errors:
*
* {
* "INNER_ARRAY_ERROR_minlength": {
* isArrayError: true,
* originalKey: "minlength",
* entries: [
* {
* index: 0,
* errorData: {
* requiredLength: 5,
* actualLength: 4
* }
* },
* {
* index: 2,
* errorData: {
* requiredLength: 5,
* actualLength: 3
* }
* },
* ]
* },
* "minlength": {
* requiredLength: 5,
* actualLength: 3
* }
* }
*
* @param validator A standard Angular synchronous validator function.
*/
export function validateArrayElements(validator) {
return (control) => {
const values = control.value;
if (!Array.isArray(values)) {
return { valueNotArray: true };
}
const validationErrors = values.map(value => validator(new FormControl(value)));
const convertedErrors = generateArrayRelatedErrors(validationErrors);
return convertedErrors;
};
}
/**
* Async version of validateArrayElements.
*
* Note that Angular by design doesn't execute async validators if synchronous validators returns any error.
* @param validator A standard Angular asynchronous validator function.
*/
export function asyncValidateArrayElements(validator) {
return (control) => {
const values = control.value;
if (!Array.isArray(values)) {
return of({ valueNotArray: true });
}
const observables = values.map(value => validator(new FormControl(value)));
return forkJoin(observables).pipe(map(errors => generateArrayRelatedErrors(errors)));
};
}
function generateArrayRelatedErrors(errors) {
const errorObject = {};
errors.forEach((error, index) => {
if (!error) {
return;
}
const errorKeys = Object.keys(error);
if (errorKeys.length) {
errorKeys.forEach(key => {
const prefixedKey = ARRAY_VALIDATION_PREFIX + key;
if (!errorObject[prefixedKey]) {
errorObject[prefixedKey] = { isArrayError: true, originalKey: key, entries: [] };
}
errorObject[prefixedKey].entries.push({ index, errorData: error[key] });
});
}
});
return Object.keys(errorObject).length ? errorObject : null;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGUtYXJyYXktZWxlbWVudHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9jb3JlL2Zvcm1zL3ZhbGlkYXRlLWFycmF5LWVsZW1lbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFHTCxXQUFXLEVBR1osTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQUUsUUFBUSxFQUFjLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNoRCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFckMsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUcsb0JBQW9CLENBQUM7QUFZNUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1ERztBQUNILE1BQU0sVUFBVSxxQkFBcUIsQ0FBQyxTQUFzQjtJQUMxRCxPQUFPLENBQUMsT0FBd0IsRUFBNkMsRUFBRTtRQUM3RSxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQzdCLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDM0IsT0FBTyxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsQ0FBQztRQUNqQyxDQUFDO1FBQ0QsTUFBTSxnQkFBZ0IsR0FBdUIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUM5RCxTQUFTLENBQUMsSUFBSSxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FDbEMsQ0FBQztRQUNGLE1BQU0sZUFBZSxHQUEwQiwwQkFBMEIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQzVGLE9BQU8sZUFBZSxDQUFDO0lBQ3pCLENBQUMsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSwwQkFBMEIsQ0FBQyxTQUEyQjtJQUNwRSxPQUFPLENBQUMsT0FBd0IsRUFBZ0MsRUFBRTtRQUNoRSxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQzdCLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDM0IsT0FBTyxFQUFFLENBQUMsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUNyQyxDQUFDO1FBQ0QsTUFBTSxXQUFXLEdBRWIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFM0QsT0FBTyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLDBCQUEwQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2RixDQUFDLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUywwQkFBMEIsQ0FBQyxNQUFzQztJQUN4RSxNQUFNLFdBQVcsR0FBMEIsRUFBRSxDQUFDO0lBRTlDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUU7UUFDOUIsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1gsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3JDLElBQUksU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3JCLFNBQVMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7Z0JBQ3RCLE1BQU0sV0FBVyxHQUFHLHVCQUF1QixHQUFHLEdBQUcsQ0FBQztnQkFDbEQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO29CQUM5QixXQUFXLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxDQUFDO2dCQUNuRixDQUFDO2dCQUNELFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQzFFLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDOUQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFic3RyYWN0Q29udHJvbCxcbiAgQXN5bmNWYWxpZGF0b3JGbixcbiAgRm9ybUNvbnRyb2wsXG4gIFZhbGlkYXRpb25FcnJvcnMsXG4gIFZhbGlkYXRvckZuXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IGZvcmtKb2luLCBPYnNlcnZhYmxlLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5leHBvcnQgY29uc3QgQVJSQVlfVkFMSURBVElPTl9QUkVGSVggPSAnSU5ORVJfQVJSQVlfRVJST1JfJztcblxuZXhwb3J0IHR5cGUgQXJyYXlWYWxpZGF0aW9uRXJyb3JzID0ge1xuICBba2V5OiBzdHJpbmddOiBBcnJheVZhbGlkYXRpb25FcnJvclZhbHVlO1xufTtcblxuZXhwb3J0IHR5cGUgQXJyYXlWYWxpZGF0aW9uRXJyb3JWYWx1ZSA9IHtcbiAgaXNBcnJheUVycm9yOiB0cnVlO1xuICBvcmlnaW5hbEtleTogc3RyaW5nO1xuICBlbnRyaWVzOiBBcnJheTx7IGluZGV4OiBudW1iZXI7IGVycm9yRGF0YTogdW5rbm93biB9Pjtcbn07XG5cbi8qKlxuICogVGhpcyBtZXRob2QgY2FuIGFsdGVyIGhvdyB2YWxpZGF0b3JzIHdvcmsuIEl0IGNhbiBiZSB1c2VkIGluIGNhc2VzIHdoZXJlIHRoZXJlIGlzIG5lZWQgdG8gdmFsaWRhdGUgRm9ybUNvbnRyb2xcbiAqIHRoYXQgYXMgdmFsdWUsIHRha2VzIGFycmF5IG9mIGVsZW1lbnRzLiBUaGlzIGFsbG93cyB0byByZXVzZSB2YWxpZGF0b3JzLCB0aGF0IHdvcmtzIGZvciBzdWNoIGVsZW1lbnRzLlxuICogRm9yIGV4YW1wbGUgaWYgIFZhbGlkYXRvcnMubWluTGVuZ3RoKDMpIGlzIHVzZWQgb24gY29udHJvbCB0aGF0IHRha2VzIHN0cmluZyBhcyB2YWx1ZSwgdmFsaWRhdG9yIHdpbGwgcmV0dXJuIGVycm9yXG4gKiBpZiBzdHJpbmcgaXMgbGVzcyB0aGFuIDMgY2hhcmFjdGVycy4gSWYgc2FtZSBpcyBkb25lIG9uIGFycmF5IG9mIHN0cmluZ3MsIHZhbGlkYXRvciB3aWxsIHJldHVybiBlcnJvciBpZiBhcnJheVxuICogaGFzIGxlc3MgdGhhbiAzIGVsZW1lbnRzLlxuICpcbiAqIHZhbGlkYXRlQXJyYXlFbGVtZW50cyhWYWxpZGF0b3JzLm1pbkxlbmd0aCgzKSkgbWV0aG9kIG1ha2VzIGl0IHBvc3NpYmxlIHRvIGNoZWNrIGV2ZXJ5IG1lbWJlciBvZiBhcnJheSBpZiBpdCBoYXMgbWluaW11bSAzIGNoYXJhY3RlcnMuXG4gKiBJZiB0aGVyZSBhcmUgZWxlbWVudHMgdGhhdCByYWlzZSBlcnJvciwgaXQgd2lsbCBiZSBwb3NzaWJsZSB0byBleHRyYWN0IHRoZXNlIGVycm9ycyB1c2luZyBpdGVtIGluZGV4LlxuICpcbiAqIEFzIGEgZXhhbXBsZSwgdGhpcyBjYW4gYmUgdXNlZCBmb3IgY3VzdG9tIGZvcm0gZWxlbWVudHMsIHdoaWNoIG1hbmlwdWxhdGVzIGFycmF5IG9mIGVsZW1lbnRzLFxuICogYW5kIHRoZXJlIGlzIG5lZWQgdG8gZGlzcGxheSBjb3JyZXNwb25kaW5nIGVycm9yIG1lc3NhZ2VzIGZvciBldmVyeSBhcnJheSBtZW1iZXIgdGhhdCBpcyBkaXNwbGF5ZWQsIHdoaWxlIHN0aWxsIHVzaW5nXG4gKiBBbmd1bGFyJ3MgVmFsaWRhdGlvbiBhcHByb2FjaC5cbiAqXG4gKiBFcnJvcnMgdGhhdCBhcmUgZ2VuZXJhdGVkIGJ5IHRoaXMgaGVscGVyIGFyZSBwcmVmaXhlZCB3aXRoICdJTk5FUl9BUlJBWV9FUlJPUl8nLiBSZWFzb24gZm9yIHRoaXMgaXMgdG8gcHJldmVudCBvdmVyd3JpdGluZyBub3JtYWwgdmFsaWRhdGlvblxuICogZXJyb3JzIHRoYXQgY291bGQgaGF2ZSBzYW1lIGtleVxuICpcbiAqIEBFeGFtcGxlXG4gKlxuICogbGV0IGNvbnRyb2wgPSBuZXcgRm9ybUNvbnRyb2woWycxMjM0JywgJzEyMzQ1NicsICcxMjMnLCBbVmFsaWRhdG9ycy5taW5MZW5ndGgoNSksIHZhbGlkYXRlQXJyYXlFbGVtZW50cyhWYWxpZGF0b3JzLm1pbkxlbmd0aCg1KSldIF0pXG4gKlxuICogdGhpcyBGb3JtQ29udHJvbCBoYXMgdmFsaWRhdGlvbiBlcnJvcnM6XG4gKlxuICoge1xuICogICBcIklOTkVSX0FSUkFZX0VSUk9SX21pbmxlbmd0aFwiOiB7XG4gKiAgICAgIGlzQXJyYXlFcnJvcjogdHJ1ZSxcbiAqICAgICAgb3JpZ2luYWxLZXk6IFwibWlubGVuZ3RoXCIsXG4gKiAgICAgIGVudHJpZXM6IFtcbiAqICAgICAgICB7XG4gKiAgICAgICAgICBpbmRleDogMCxcbiAqICAgICAgICAgIGVycm9yRGF0YToge1xuICogICAgICAgICAgICByZXF1aXJlZExlbmd0aDogNSxcbiAqICAgICAgICAgICAgYWN0dWFsTGVuZ3RoOiA0XG4gKiAgICAgICAgICB9XG4gKiAgICAgICAgfSxcbiAqICAgICAgICB7XG4gKiAgICAgICAgICBpbmRleDogMixcbiAqICAgICAgICAgIGVycm9yRGF0YToge1xuICogICAgICAgICAgICByZXF1aXJlZExlbmd0aDogNSxcbiAqICAgICAgICAgICAgYWN0dWFsTGVuZ3RoOiAzXG4gKiAgICAgICAgICB9XG4gKiAgICAgICAgfSxcbiAqICAgICAgXVxuICogICAgfSxcbiAqICAgXCJtaW5sZW5ndGhcIjoge1xuICogICAgIHJlcXVpcmVkTGVuZ3RoOiA1LFxuICogICAgIGFjdHVhbExlbmd0aDogM1xuICogICB9XG4gKiB9XG4gKlxuICogQHBhcmFtIHZhbGlkYXRvciBBIHN0YW5kYXJkIEFuZ3VsYXIgc3luY2hyb25vdXMgdmFsaWRhdG9yIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVBcnJheUVsZW1lbnRzKHZhbGlkYXRvcjogVmFsaWRhdG9yRm4pOiBWYWxpZGF0b3JGbiB7XG4gIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sKTogeyB2YWx1ZU5vdEFycmF5IH0gfCBBcnJheVZhbGlkYXRpb25FcnJvcnMgPT4ge1xuICAgIGNvbnN0IHZhbHVlcyA9IGNvbnRyb2wudmFsdWU7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHZhbHVlcykpIHtcbiAgICAgIHJldHVybiB7IHZhbHVlTm90QXJyYXk6IHRydWUgfTtcbiAgICB9XG4gICAgY29uc3QgdmFsaWRhdGlvbkVycm9yczogVmFsaWRhdGlvbkVycm9yc1tdID0gdmFsdWVzLm1hcCh2YWx1ZSA9PlxuICAgICAgdmFsaWRhdG9yKG5ldyBGb3JtQ29udHJvbCh2YWx1ZSkpXG4gICAgKTtcbiAgICBjb25zdCBjb252ZXJ0ZWRFcnJvcnM6IEFycmF5VmFsaWRhdGlvbkVycm9ycyA9IGdlbmVyYXRlQXJyYXlSZWxhdGVkRXJyb3JzKHZhbGlkYXRpb25FcnJvcnMpO1xuICAgIHJldHVybiBjb252ZXJ0ZWRFcnJvcnM7XG4gIH07XG59XG5cbi8qKlxuICogQXN5bmMgdmVyc2lvbiBvZiB2YWxpZGF0ZUFycmF5RWxlbWVudHMuXG4gKlxuICogTm90ZSB0aGF0IEFuZ3VsYXIgYnkgZGVzaWduIGRvZXNuJ3QgZXhlY3V0ZSBhc3luYyB2YWxpZGF0b3JzIGlmIHN5bmNocm9ub3VzIHZhbGlkYXRvcnMgcmV0dXJucyBhbnkgZXJyb3IuXG4gKiBAcGFyYW0gdmFsaWRhdG9yIEEgc3RhbmRhcmQgQW5ndWxhciBhc3luY2hyb25vdXMgdmFsaWRhdG9yIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXN5bmNWYWxpZGF0ZUFycmF5RWxlbWVudHModmFsaWRhdG9yOiBBc3luY1ZhbGlkYXRvckZuKTogQXN5bmNWYWxpZGF0b3JGbiB7XG4gIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sKTogT2JzZXJ2YWJsZTxWYWxpZGF0aW9uRXJyb3JzPiA9PiB7XG4gICAgY29uc3QgdmFsdWVzID0gY29udHJvbC52YWx1ZTtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodmFsdWVzKSkge1xuICAgICAgcmV0dXJuIG9mKHsgdmFsdWVOb3RBcnJheTogdHJ1ZSB9KTtcbiAgICB9XG4gICAgY29uc3Qgb2JzZXJ2YWJsZXM6IEFycmF5PFxuICAgICAgUHJvbWlzZTxWYWxpZGF0aW9uRXJyb3JzIHwgbnVsbD4gfCBPYnNlcnZhYmxlPFZhbGlkYXRpb25FcnJvcnMgfCBudWxsPlxuICAgID4gPSB2YWx1ZXMubWFwKHZhbHVlID0+IHZhbGlkYXRvcihuZXcgRm9ybUNvbnRyb2wodmFsdWUpKSk7XG5cbiAgICByZXR1cm4gZm9ya0pvaW4ob2JzZXJ2YWJsZXMpLnBpcGUobWFwKGVycm9ycyA9PiBnZW5lcmF0ZUFycmF5UmVsYXRlZEVycm9ycyhlcnJvcnMpKSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRlQXJyYXlSZWxhdGVkRXJyb3JzKGVycm9yczogQXJyYXk8VmFsaWRhdGlvbkVycm9ycyB8IG51bGw+KTogQXJyYXlWYWxpZGF0aW9uRXJyb3JzIHtcbiAgY29uc3QgZXJyb3JPYmplY3Q6IEFycmF5VmFsaWRhdGlvbkVycm9ycyA9IHt9O1xuXG4gIGVycm9ycy5mb3JFYWNoKChlcnJvciwgaW5kZXgpID0+IHtcbiAgICBpZiAoIWVycm9yKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGVycm9yS2V5cyA9IE9iamVjdC5rZXlzKGVycm9yKTtcbiAgICBpZiAoZXJyb3JLZXlzLmxlbmd0aCkge1xuICAgICAgZXJyb3JLZXlzLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgY29uc3QgcHJlZml4ZWRLZXkgPSBBUlJBWV9WQUxJREFUSU9OX1BSRUZJWCArIGtleTtcbiAgICAgICAgaWYgKCFlcnJvck9iamVjdFtwcmVmaXhlZEtleV0pIHtcbiAgICAgICAgICBlcnJvck9iamVjdFtwcmVmaXhlZEtleV0gPSB7IGlzQXJyYXlFcnJvcjogdHJ1ZSwgb3JpZ2luYWxLZXk6IGtleSwgZW50cmllczogW10gfTtcbiAgICAgICAgfVxuICAgICAgICBlcnJvck9iamVjdFtwcmVmaXhlZEtleV0uZW50cmllcy5wdXNoKHsgaW5kZXgsIGVycm9yRGF0YTogZXJyb3Jba2V5XSB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBPYmplY3Qua2V5cyhlcnJvck9iamVjdCkubGVuZ3RoID8gZXJyb3JPYmplY3QgOiBudWxsO1xufVxuIl19