UNPKG

@terminus/ngx-tools

Version:

[![CircleCI][circle-badge]][circle-link] [![codecov][codecov-badge]][codecov-project] [![semantic-release][semantic-release-badge]][semantic-release] [![MIT License][license-image]][license-url] <br> [![NPM version][npm-version-image]][npm-url] [![Github

902 lines (872 loc) 29.4 kB
import { isNull, isAbstractControl, isString, isBoolean, isArray, isUndefined, isNumber } from '@terminus/ngx-tools/type-guards'; import { FormGroup } from '@angular/forms'; import { __read, __assign, __values } from 'tslib'; import { coerceNumberProperty, coerceDateProperty } from '@terminus/ngx-tools/coercion'; import { zip, range, throwError, timer, ReplaySubject } from 'rxjs'; import { async } from 'rxjs/internal/scheduler/async'; import { retryWhen, mergeMap, take, takeUntil } from 'rxjs/operators'; /** * Helper function to abbreviate a number * * @param input - The number to be abbreviated. * @param decimalPlace - The decimals users define for final abbreviated number. Default to 1. * @returns The abbreviated number * * @example * abbreviateNumber(1234, '1') // Returns: '1.2K' */ function abbreviateNumber(input, decimalPlace) { if (decimalPlace === void 0) { decimalPlace = 1; } var SCALE_NUMBER = 3; var MATH_POWER = 10; if (!input) { return ''; } var baseNumberAndExponent = input .toExponential() .split('e+') .map(function (el) { return +el; }); if (baseNumberAndExponent[1] < SCALE_NUMBER) { return input.toString(); } var scaleLevel = baseNumberAndExponent[1] % SCALE_NUMBER; baseNumberAndExponent[0] = baseNumberAndExponent[0] * Math.pow(MATH_POWER, scaleLevel); var calculatedScale = [ '', 'K', 'M', 'B', 'T', ][(baseNumberAndExponent[1] - scaleLevel) / SCALE_NUMBER]; var newNumber = baseNumberAndExponent[0].toFixed(decimalPlace).toString(); return newNumber + calculatedScale; } /** * A helper function to apply TypeScript mixins * * https://www.typescriptlang.org/docs/handbook/mixins.html * * @param derivedCtor - The mixin target class * @param baseCtors - An array of classes to combine into the target class * @returns The mixed class * * @example * applyMixins(SmartObject, [Disposable, Activatable]); */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function applyMixins(derivedCtor, baseCtors) { baseCtors.forEach(function (baseCtor) { Object.getOwnPropertyNames(baseCtor.prototype).forEach(function (name) { derivedCtor.prototype[name] = baseCtor.prototype[name]; }); }); } /** * Determine if an object exists in an array * * @param object - The object to look for in the array * @param array - The array to search through * @param comparator - The function to determine what object values to compare * @returns True if a match was found * * @example * const arr = [{id: 1}, {id: 2}, {id: 3}]; * const comparator = (v) => v.id; * arrayContainsObject({id: 2}, array, comparator); // Returns: true */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function arrayContainsObject(object, array, comparator) { var hasDuplicate = false; // eslint-disable-next-line @typescript-eslint/prefer-for-of for (var i = 0; i < array.length; i++) { if (comparator(array[i]) === comparator(object)) { hasDuplicate = true; break; } } return hasDuplicate; } /** * Create an array with `null` & `undefined` values removed * * @param arr - The array to compact * @returns The compacted array * * @example * compactArray(['hi', null, 2, true, undefined]) // Returns: ['hi', 2, true] */ function compactArray(arr) { if (!arr || arr.length < 1) { return undefined; } var valuesToReturn = []; arr.map(function (i) { if (i === null || i === undefined || '') { return; } valuesToReturn.push(i); }); return valuesToReturn; } /** * Return a function, that, as long as it continues to be invoked, will not be triggered. The * function will be called after it stops being called for N milliseconds. * * @param func - The function to call after the debounce period * @param wait - The length of time to wait between calls (ms) * @param immediate - Whether the debounced function should be fired immediately * @param windowRef - A reference to the global window object * @returns The debounced function * * @example * const myFunc = () => {console.log('hi!')}; * const myDebouncedFunc = debounce(myFunc, 200); * myDebouncedFunc(); * myDebouncedFunc(); * myDebouncedFunc(); * // 'hi!' will only be logged once */ function debounce(func, wait, immediate, windowRef) { if (immediate === void 0) { immediate = false; } if (windowRef === void 0) { windowRef = window; } var timeout = null; return function () { var context = this; var args = arguments; var later = function () { timeout = null; if (!immediate) { func.apply(context, args); } }; var callNow = immediate && !timeout; if (timeout) { clearTimeout(timeout); } timeout = windowRef.setTimeout(later, wait); if (callNow) { func.apply(context, args); } }; } /** * Define the typeCache which will hold all action types for the entire application */ var typeCache = {}; /** * Ensure you only define an action once in the entirety of the application * * @param label - The action label * @returns uniqueLabel - The unique label * * @example * defineType('[log-in] User log in') as '[log-in] User log in'; */ function defineType(label) { // Verify the label does not already exist in the cache if (typeCache[label]) { throw new Error("Action type '" + label + "' is not unique!"); } // Save the label to the cache typeCache[label] = true; return label; } /** * Ensure action is defined only once in the entirety of the application * * @param typeEnum * * @example * export enum actionTypes { * AssignState = '[mock-meta-reducer] Assign State', * }; * defineTypeEnum(actionTypes); */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function defineTypeEnum(typeEnum) { for (var val in typeEnum) { // istanbul ignore else if (typeEnum.hasOwnProperty(val)) { defineType(typeEnum[val]); } } } /** * Reset the type cache * NOTE: FOR TESTS ONLY */ function resetTypeCache() { typeCache = {}; } /* eslint-disable @typescript-eslint/no-magic-numbers */ /** * Generate a canonically formatted UUID that is Version 1 through 5 and is the appropriate Variant as per RFC4122. * * @returns The UUID * * @example * generateUUID() // Returns a UUID such as: `f4ee5eed-ed19-3681-713e-907a23ed7858` */ function generateUUID() { var buf = new Uint16Array(8); window.crypto.getRandomValues(buf); var S4 = function (num) { var ret = num.toString(16); while (ret.length < 4) { ret = "0" + ret; } return ret; }; return (S4(buf[0]) + S4(buf[1]) + "-" + S4(buf[2]) + "-" + S4(buf[3]) + "-" + S4(buf[4]) + "-" + S4(buf[5]) + S4(buf[6]) + S4(buf[7])); } /** * Return the value of a FormControl within a FormGroup * * @param form - The FormGroup that contains the control * @param controlName - The name of the control * @returns The value * * @example * getFormControlValue(myFormGroup, 'myControl'); * getFormControlValue<boolean>(myFormGroup, 'myControl'); */ function getFormControlValue(form, controlName) { if (!form || !controlName) { return undefined; } var control = form.get(controlName); return !isNull(control) && isAbstractControl(control) ? control.value : undefined; } /** * Return an object containing arrays organized by property * * @param array - The array to split * @param key - The object property to split by * @returns An object containing arrays separated by property value * * @example * interface MyObj { * a: string; * b: number; * } * const myArray: MyObj[] = [{a: 'foo', b: 1}, {a: 'bar', b: 6}, {a: 'foo', b: 6}]; * groupBy<MyObj, keyof MyObj>(myArray, 'a'); * Returns: * { * foo: [{a: 'foo', b: 1}, {a: 'foo', b: 6}], * bar: [{a: 'bar', b: 6}], * } */ function groupBy(array, key) { var initialValue = {}; return array.reduce(function (accumulator, x) { // eslint-disable-next-line @typescript-eslint/no-explicit-any var idx = x[key]; // Create an array for the property if one does not exist if (!accumulator[idx]) { accumulator[idx] = []; } // Add the item to the property array accumulator[idx].push(x); return accumulator; }, initialValue); } /** * Determine if a form control has a required validator * * @param formItem - The control or form group to check * @returns If a required control is found * * @example * const ctrl = new FormControl(null, [Validators.required]; * const group = new FormGroup({myControl: [null, [Validators.required]]}); * hasRequiredControl(ctrl); // Returns: true * hasRequiredControl(group); // Returns: true */ function hasRequiredControl(formItem) { if (!formItem) { return false; } // Dealing with FormGroup if (formItem instanceof FormGroup) { var isRequired = false; // Check each control within the group // eslint-disable-next-line @typescript-eslint/prefer-for-of for (var i = 0; i < Object.keys(formItem.controls).length; i += 1) { var control = formItem.controls[Object.keys(formItem.controls)[i]]; isRequired = controlHasRequiredField(control); // Break out of the loop when we find the first required control if (isRequired) { break; } } return isRequired; } // Dealing with AbstractControl return controlHasRequiredField(formItem); } /** * Determine if a form control has a required validator * * @param control - The control to test * @returns If the control is required * * @example * const ctrl = new FormControl(null, [Validators.required]; * controlHasRequiredField(ctrl); // Returns: true */ function controlHasRequiredField(control) { var validator = control.validator ? control.validator({}) : null; return !!(validator && validator.required); } var DEFAULT_JITTER_FACTOR = .3; var DEFAULT_BACK_OFF_TIME = 2; var DEFAULT_BASE_WAIT_TIME = 100; /** * Calculate retry timing * * `jitter`: "Slight irregular movement, variation, or unsteadiness, * especially in an electrical signal or electronic device" * * @param options - The options object * - `jitter`: If the duration should be affected by a jitter effect * - `jitterFactor`: How widely the jitter effect should vary * - `backOffFactor`: How quickly the duration should back off * - `baseWaitTime`: The base time when determining sleep duration * @returns The duration to sleep * * @example * const calcOpts: DelayCalculator = { * jitter: true, * jitterFactor: .3, * backOffFactor: 2, * baseWaitTime: 100, * } * // Create a retrier with a custom backoff * retryWithBackoff({retries: 3, delayCalculator: exponentialBackoffDelayCalculator(calcOpts)}) */ var exponentialBackoffDelayCalculator = function (_a) { var _b = _a.jitter, jitter = _b === void 0 ? true : _b, _c = _a.jitterFactor, jitterFactor = _c === void 0 ? DEFAULT_JITTER_FACTOR : _c, _d = _a.backOffFactor, backOffFactor = _d === void 0 ? DEFAULT_BACK_OFF_TIME : _d, _e = _a.baseWaitTime, baseWaitTime = _e === void 0 ? DEFAULT_BASE_WAIT_TIME : _e; return function (attempt) { var sleepDuration = baseWaitTime * Math.pow(backOffFactor, attempt); if (jitter) { sleepDuration *= (1 - (jitterFactor * Math.random())); } return sleepDuration; }; }; var DEFAULT_RETRY_COUNT = 2; var ERROR_CODE_TOO_MANY_REQUESTS = 429; var ERROR_CODE_500_MIN = 500; var ERROR_CODE_500_MAX = 599; var httpRetryer = function (_a) { var _b = _a.retries, retries = _b === void 0 ? DEFAULT_RETRY_COUNT : _b, _c = _a.delayCalculator, delayCalculator = _c === void 0 ? exponentialBackoffDelayCalculator({}) : _c, _d = _a.scheduler, scheduler = _d === void 0 ? async : _d; return retryWhen(function (errors) { return zip(errors, range(1, retries + 1)).pipe(mergeMap(function (_a) { var _b = __read(_a, 2), err = _b[0], retry = _b[1]; if (retry > retries || !isConsideredError(err)) { return throwError(err); } var waitTime = delayCalculator(retry); if (err.status === ERROR_CODE_TOO_MANY_REQUESTS) { var headerWaitTime = extractRetryAfterTime(err); waitTime = headerWaitTime || waitTime; } return timer(waitTime, scheduler).pipe(take(1)); })); }); }; /** * @param err */ function extractRetryAfterTime(err) { var retryHeaderValue = err.headers.get('Retry-After'); if (retryHeaderValue) { return coerceNumberProperty(retryHeaderValue, null) || coerceDateProperty(retryHeaderValue, null); } return null; } /** * @param err */ function isConsideredError(err) { if (err.hasOwnProperty('status') && err.hasOwnProperty('headers')) { var e = err; return e.status === 0 || e.status === ERROR_CODE_TOO_MANY_REQUESTS || (e.status >= ERROR_CODE_500_MIN && e.status <= ERROR_CODE_500_MAX); } return false; } /** * Helper function to parse an object with deep keys * * @param object - An object with key as string or string * @param keys - A string or array of strings * @returns String value at the lowest layer or object itself * * @example * objectDeepParse(myObject, ['foo', 'bar']) // Returns: myObject.foo.bar if found * objectDeepParse(myObject, 'foo.bar') // Returns: myObject.foo.bar if found */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function objectDeepParse(object, keys) { if (isString(object) || isBoolean(object) || !object) { return object; } keys = isArray(keys) ? keys : keys.split('.'); object = object[keys[0]]; if (object && keys.length > 1) { return objectDeepParse(object, keys.slice(1)); } return object; } /** * Utility class to assist with pulling specific values from a `SimpleChanges` object. */ var NgChangeObjectValueParser = /** @class */ (function () { function NgChangeObjectValueParser() { } /** * Function to parse previousValue from triggered by changes on ngOnChange * * @param changes - SimpleChanges * @param path - string * @returns lowest layer value or changes object itself when path cannot be parsed * * @example * valueParser.getOldValue(myChanges, 'my.path') */ // eslint-disable-next-line @typescript-eslint/no-explicit-any NgChangeObjectValueParser.getOldValue = function (changes, path) { var _a = __read(this.parsePath(path), 2), keys = _a[0], key = _a[1]; return (key && changes[key]) ? objectDeepParse(changes[key].previousValue, keys) : undefined; }; /** * Function to parse currentValue from triggered by changes on ngOnChange * * @param changes - SimpleChanges * @param path - string * @returns lowest layer value or changes object itself when path cannot be parsed * * @example * valueParser.getNewValue(myChanges, 'my.path') */ // eslint-disable-next-line @typescript-eslint/no-explicit-any NgChangeObjectValueParser.getNewValue = function (changes, path) { var _a = __read(this.parsePath(path), 2), keys = _a[0], key = _a[1]; return (key && changes[key]) ? objectDeepParse(changes[key].currentValue, keys) : undefined; }; /** * Function to parse path to get keys for each layer * * @param path - string * @returns an array of two elements, one being an array of all the keys except first one, one being the first key * * @example * valueParser.parsePath('my.path') // Returns: [['my'], 'path'] */ NgChangeObjectValueParser.parsePath = function (path) { var keys = path.split('.'); var key = keys.shift(); if (!key) { key = keys[0]; } return [keys, key]; }; return NgChangeObjectValueParser; }()); /** * Helper function to determine if a specific value has changed * * @param changes - The object of changes * @param path - The object path in question * @returns True if the value has changed * * @example * inputHasChanged(changesObject, 'myInputName') */ function inputHasChanged(changes, path) { if (!changes || !path) { return undefined; } var oldValue = NgChangeObjectValueParser.getOldValue(changes, path); var newValue = NgChangeObjectValueParser.getNewValue(changes, path); return oldValue !== newValue; } /** * Helper function to determine if input is unset. * * @param x - the input being tested * @returns boolean * * @example * isUnset(null); // Returns: true * isUnset(undefined); // Returns: true * isUnset('hello'); // Returns: false */ // eslint-disable-next-line @typescript-eslint/no-explicit-any var isUnset = function (x) { return isNull(x) || isUndefined(x); }; /** * Placeholder function. * * @returns Undefined */ var noop = function () { return void 0; }; /** * Helper function to get an object with deep keys * * @param object - The object to query. * @param path - The string path of the property to get. * @param defaultValue - (optional) - The value returned for undefined resolved values. * @returns The updated object * * @example * const myObj = {foo: {bar: 'baz', bing: 'bang'}}; * objectDeepGet(myObj, 'foo.bar') // Returns: 'baz' * objectDeepGet(myObj, 'does.not.exist', 'hi') // Returns: 'hi' */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function objectDeepGet(object, path, defaultValue) { if (!object) { return defaultValue; } var keys = path.split('.'); object = object[keys[0]]; if (object && keys.length > 1) { return objectDeepGet(object, keys.slice(1).join('.'), defaultValue); } if (object === undefined && defaultValue) { return defaultValue; } return object; } /** * Helper function to get an object with deep keys * * @param obj - The object to modify. * @param keys - The path of the property to set. * @param value - The value to set. * @returns The updated object * * @example * const myObj: MyObjType = { * foo: { * bar: { * baz: true, * }, * }, * }; * const updatedObject = objectDeepSet(myObj, 'foo.bar.baz', false); * const updatedObject = objectDeepSet<boolean, MyObjType>(myObj, 'foo.bar.baz', false); */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function objectDeepSet(obj, keys, value) { var _a, _b; var paths = keys.split('.'); if (paths.length === 1) { var path_1 = paths[0]; return (__assign(__assign({}, obj), (_a = {}, _a[path_1] = value, _a))); } var _c = __read(paths), path = _c[0], remainingPaths = _c.slice(1); var nestedObj = obj[path]; var newNestedObj = objectDeepSet(nestedObj, remainingPaths.join('.'), value); return (__assign(__assign({}, obj), (_b = {}, _b[path] = newNestedObj, _b))); } var DEFAULT_RETRY_COUNT$1 = 3; /** * Return the difference in time in words * * @param options - The options object * - `retries`: How many times it should retry before throwing an error * - `delayCalculator`: The calculator to determine the delay timing * @returns The observable timer * * @example * return this.exampleDatabase.getSomething() * .pipe( * map((res: MyResponse) => { * if (res) { * return res; * } else { * return null; * } * }), * retryWithBackoff({}), // Using default options * ) * ; */ var retryWithBackoff = function (_a) { var _b = _a.retries, retries = _b === void 0 ? DEFAULT_RETRY_COUNT$1 : _b, _c = _a.delayCalculator, delayCalculator = _c === void 0 ? exponentialBackoffDelayCalculator({}) : _c; return retryWhen(function (errors) { return zip(errors, range(1, retries)) .pipe(mergeMap(function (_a) { var _b = __read(_a, 2), err = _b[0], retry = _b[1]; if (retry >= retries) { return throwError(err); } return timer(delayCalculator(retry)); })); }); }; /** * Helper function to return an array of values from an hash object * * @param keys - The array containing the key values (number|string) to retrieve from the hash * @param hash - The object to pull values from * @returns The array of values that match keys * * @example * const tactic1: MyType = { * id: 1, * name: 'tactic1', * goal: 'goal1', * } * const tactic2: MyType = { * id: 2, * name: 'tactic2', * goal: 'goal2', * } * const tactics = { 1: tactic1, 2: tactic2 } * returnValuesByKeys<MyType>([1], tactics) // Returns: `[tactic1]` */ function returnValuesByKeys(keys, hash) { var e_1, _a; var stringyKeys = keys.map(function (id) { return id.toString(); }); var values = []; try { for (var stringyKeys_1 = __values(stringyKeys), stringyKeys_1_1 = stringyKeys_1.next(); !stringyKeys_1_1.done; stringyKeys_1_1 = stringyKeys_1.next()) { var key = stringyKeys_1_1.value; // istanbul ignore else if (hash[key]) { values.push(hash[key]); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (stringyKeys_1_1 && !stringyKeys_1_1.done && (_a = stringyKeys_1.return)) _a.call(stringyKeys_1); } finally { if (e_1) throw e_1.error; } } return values; } /** * Round a number * * Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round#A_better_solution * * @param num - The number to round (also accepting strings for exponential support) * @param precision - How precise to make the rounding * @returns The rounded number * * @example * roundNumber(1.050, 1) // Returns: `1.1` * roundNumber(3456.3456, 1) // Returns: `3456.3` * roundNumber(3456.3456, -2) // Returns: `3500` * roundNumber('1.23e+5', -4) // Returns: `120000` */ function roundNumber(num, precision) { if (precision === void 0) { precision = 0; } if (!isNumber(num)) { return undefined; } var shift = function (innerNum, innerPrecision) { var numArray = innerNum.toString().split('e'); return +(numArray[0] + "e" + (numArray[1] ? (+numArray[1] + innerPrecision) : innerPrecision)); }; return shift(Math.round(shift(num, +precision)), -precision); } /** * Set the value of a FormControl * * @param form - The FormGroup * @param controlName - The name of the control * @param controlValue - The value to set the control to * * @example * setFormControlValue<number>(myForm, 'budget', 50); */ function setFormControlValue(form, controlName, controlValue) { if (!form || !controlName) { return; } var control = form.get(controlName); if (control) { control.setValue(controlValue); } } /* * 'Inspired' by https://github.com/sindresorhus/camelcase */ /** * Function that preserves camel case * * @param input - The string input * @returns The adjusted string */ function preserveCamelCase(input) { var isLastCharLower = false; var isLastCharUpper = false; var isLastLastCharUpper = false; for (var i = 0; i < input.length; i++) { var c = input[i]; if (isLastCharLower && /[a-zA-Z]/.test(c) && c.toUpperCase() === c) { input = input.slice(0, i) + "-" + input.slice(i); isLastCharLower = false; isLastLastCharUpper = isLastCharUpper; isLastCharUpper = true; i++; } else if (isLastCharUpper && isLastLastCharUpper && /[a-zA-Z]/.test(c) && c.toLowerCase() === c) { input = input.slice(0, i - 1) + "-" + input.slice(i - 1); isLastLastCharUpper = isLastCharUpper; isLastCharUpper = false; isLastCharLower = true; } else { isLastCharLower = c.toLowerCase() === c; isLastLastCharUpper = isLastCharUpper; isLastCharUpper = c.toUpperCase() === c; } } return input; } /** * Post process a conversion into PascalCase if necessary * * @param x - The string * @param pascalCase - A boolean representing if the string should be converted to PascalCase * @returns The final string */ var postProcess = function (x, pascalCase) { return (pascalCase ? x.charAt(0).toUpperCase() + x.slice(1) : x); }; var ɵ0 = postProcess; /** * Convert a string to camelCase * * @param input - The string to convert * @param pascalCase - A boolean representing if the string should be converted to PascalCase * @returns The camelCase version of the string * * @example * toCamelCase('MY_TEXT') // Returns: `myText` * toCamelCase('MY_TEXT', true) // Returns: `MyText` */ function toCamelCase(input, pascalCase) { if (pascalCase === void 0) { pascalCase = false; } if (!input) { return undefined; } // Trim whitespace input = input.trim(); // Test for a single character if (input.length === 1) { return pascalCase ? input.toUpperCase() : input.toLowerCase(); } // Test if we are dealing with a single lowercased word if (/^[a-z\d]+$/.test(input)) { return postProcess(input, pascalCase); } // Test if there are any uppercase if (input !== input.toLowerCase()) { input = preserveCamelCase(input); } input = input .replace(/^[_.\- ]+/, '') .toLowerCase() .replace(/[_.\- ]+(\w|$)/g, function (m, p1) { return p1.toUpperCase(); }); return postProcess(input, pascalCase); } /** * Patch the component with unsubscribe behavior * * @param component - The component class (`this` context) * @returns An observable representing the unsubscribe event */ function componentDestroyed(component) { if (component.componentDestroyed$) { return component.componentDestroyed$; } // eslint-disable-next-line @angular-eslint/no-lifecycle-call var oldNgOnDestroy = component.ngOnDestroy; var stop$ = new ReplaySubject(); // eslint-disable-next-line @angular-eslint/no-lifecycle-call component.ngOnDestroy = function () { // istanbul ignore else if (oldNgOnDestroy) { oldNgOnDestroy.apply(component); } stop$.next(true); stop$.complete(); }; component.componentDestroyed$ = stop$.asObservable(); return component.componentDestroyed$; } /** * A pipe-able operator to unsubscribe during OnDestroy lifecycle event * * @param component - The component class (`this` context) * @returns The component wrapped in an Observable * * @example * source.pipe(untilComponentDestroyed(this)).subscribe... */ var untilComponentDestroyed = // eslint-disable-next-line max-len function (component) { return function (source) { return source.pipe(takeUntil(componentDestroyed(component))); }; }; /** * Helper function to determine if a specific value has changed * * @param changes - The object of changes * @param path - A string with keys defined, separate with '.' * @param control - The formControl * @returns True if the value has changed * * @example * ... * AngularInput: * public myInput; * AngularInput: * public myFormControl; * * ngOnChanges(changes: SimpleChanges) { * // This will update the form control's value whenever the `@Input` value changes: * updateControlOnInputChanges(changes, 'myInput', this.myFormControl)); * } * ... */ function updateControlOnInputChanges(changes, path, control) { if (!changes || !path || !control) { return false; } if (inputHasChanged(changes, path)) { var newValue = NgChangeObjectValueParser.getNewValue(changes, path); control.setValue(newValue); return true; } return false; } /** * Create version information from a version string * * @example * VERSION.full // Returns: 1.2.3 * VERSION.major // Returns: 1 * VERSION.minor // Returns: 2 * VERSION.patch // Returns: 3 */ var Version = /** @class */ (function () { function Version(full) { this.full = full; var parts = full.split('.'); var itemsToRemoveForPatch = 2; this.major = parts[0]; this.minor = parts[1]; this.patch = parts.slice(itemsToRemoveForPatch).join('.'); } return Version; }()); var VERSION = new Version('8.0.6'); /** * Generated bundle index. Do not edit. */ export { NgChangeObjectValueParser, VERSION, Version, abbreviateNumber, applyMixins, arrayContainsObject, compactArray, componentDestroyed, debounce, defineType, defineTypeEnum, exponentialBackoffDelayCalculator, generateUUID, getFormControlValue, groupBy, hasRequiredControl, httpRetryer, inputHasChanged, isUnset, noop, objectDeepGet, objectDeepParse, objectDeepSet, resetTypeCache, retryWithBackoff, returnValuesByKeys, roundNumber, setFormControlValue, toCamelCase, untilComponentDestroyed, updateControlOnInputChanges, ɵ0 }; //# sourceMappingURL=terminus-ngx-tools-utilities.js.map