angular2-schema-form
Version:
Angular2 Schema Form (DISCLAIMER: it is not related to angular-schema-form)
274 lines (273 loc) • 10 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import 'rxjs/add/observable/combineLatest';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/distinctUntilChanged';
var FormProperty = (function () {
function FormProperty(schemaValidatorFactory, validatorRegistry, schema, parent, path) {
this.validatorRegistry = validatorRegistry;
this.schema = schema;
this._value = null;
this._errors = null;
this._valueChanges = new BehaviorSubject(null);
this._errorsChanges = new BehaviorSubject(null);
this._visible = true;
this._visibilityChanges = new BehaviorSubject(true);
this.schemaValidator = schemaValidatorFactory.createValidatorFn(this.schema);
this._parent = parent;
if (parent) {
this._root = parent.root;
}
else if (this instanceof PropertyGroup) {
this._root = this;
}
this._path = path;
}
Object.defineProperty(FormProperty.prototype, "valueChanges", {
get: function () {
return this._valueChanges;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FormProperty.prototype, "errorsChanges", {
get: function () {
return this._errorsChanges;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FormProperty.prototype, "type", {
get: function () {
return this.schema.type;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FormProperty.prototype, "parent", {
get: function () {
return this._parent;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FormProperty.prototype, "root", {
get: function () {
return this._root || this;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FormProperty.prototype, "path", {
get: function () {
return this._path;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FormProperty.prototype, "value", {
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FormProperty.prototype, "visible", {
get: function () {
return this._visible;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FormProperty.prototype, "valid", {
get: function () {
return this._errors === null;
},
enumerable: true,
configurable: true
});
FormProperty.prototype.updateValueAndValidity = function (onlySelf, emitEvent) {
if (onlySelf === void 0) { onlySelf = false; }
if (emitEvent === void 0) { emitEvent = true; }
this._updateValue();
if (emitEvent) {
this.valueChanges.next(this.value);
}
this._runValidation();
if (this.parent && !onlySelf) {
this.parent.updateValueAndValidity(onlySelf, emitEvent);
}
};
/**
* @internal
*/
FormProperty.prototype._runValidation = function () {
var errors = this.schemaValidator(this._value) || [];
var customValidator = this.validatorRegistry.get(this.path);
if (customValidator) {
var customErrors = customValidator(this.value, this, this.findRoot());
errors = this.mergeErrors(errors, customErrors);
}
if (errors.length === 0) {
errors = null;
}
this._errors = errors;
this.setErrors(this._errors);
};
FormProperty.prototype.mergeErrors = function (errors, newErrors) {
if (newErrors) {
if (Array.isArray(newErrors)) {
errors = errors.concat.apply(errors, newErrors);
}
else {
errors.push(newErrors);
}
}
return errors;
};
FormProperty.prototype.setErrors = function (errors) {
this._errors = errors;
this._errorsChanges.next(errors);
};
FormProperty.prototype.extendErrors = function (errors) {
errors = this.mergeErrors(this._errors || [], errors);
this.setErrors(errors);
};
FormProperty.prototype.searchProperty = function (path) {
var prop = this;
var base = null;
var result = null;
if (path[0] === '/') {
base = this.findRoot();
result = base.getProperty(path.substr(1));
}
else {
while (result === null && prop.parent !== null) {
prop = base = prop.parent;
result = base.getProperty(path);
}
}
return result;
};
FormProperty.prototype.findRoot = function () {
var property = this;
while (property.parent !== null) {
property = property.parent;
}
return property;
};
FormProperty.prototype.setVisible = function (visible) {
this._visible = visible;
this._visibilityChanges.next(visible);
this.updateValueAndValidity();
if (this.parent) {
this.parent.updateValueAndValidity(false, true);
}
};
// A field is visible if AT LEAST ONE of the properties it depends on is visible AND has a value in the list
FormProperty.prototype._bindVisibility = function () {
var _this = this;
var visibleIf = this.schema.visibleIf;
if (typeof visibleIf === 'object' && Object.keys(visibleIf).length === 0) {
this.setVisible(false);
}
else if (visibleIf !== undefined) {
var propertiesBinding = [];
var _loop_1 = function (dependencyPath) {
if (visibleIf.hasOwnProperty(dependencyPath)) {
var property = this_1.searchProperty(dependencyPath);
if (property) {
var valueCheck = property.valueChanges.map(function (value) {
if (visibleIf[dependencyPath].indexOf('$ANY$') !== -1) {
return value.length > 0;
}
else {
return visibleIf[dependencyPath].indexOf(value) !== -1;
}
});
var visibilityCheck = property._visibilityChanges;
var and = Observable.combineLatest([valueCheck, visibilityCheck], function (v1, v2) { return v1 && v2; });
propertiesBinding.push(and);
}
else {
console.warn('Can\'t find property ' + dependencyPath + ' for visibility check of ' + this_1.path);
}
}
};
var this_1 = this;
for (var dependencyPath in visibleIf) {
_loop_1(dependencyPath);
}
Observable.combineLatest(propertiesBinding, function () {
var values = [];
for (var _i = 0; _i < arguments.length; _i++) {
values[_i] = arguments[_i];
}
return values.indexOf(true) !== -1;
}).distinctUntilChanged().subscribe(function (visible) {
_this.setVisible(visible);
});
}
};
return FormProperty;
}());
export { FormProperty };
var PropertyGroup = (function (_super) {
__extends(PropertyGroup, _super);
function PropertyGroup() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.properties = null;
return _this;
}
PropertyGroup.prototype.getProperty = function (path) {
var subPathIdx = path.indexOf('/');
var propertyId = subPathIdx !== -1 ? path.substr(0, subPathIdx) : path;
var property = this.properties[propertyId];
if (property !== null && subPathIdx !== -1 && property instanceof PropertyGroup) {
var subPath = path.substr(subPathIdx + 1);
property = property.getProperty(subPath);
}
return property;
};
PropertyGroup.prototype.forEachChild = function (fn) {
for (var propertyId in this.properties) {
if (this.properties.hasOwnProperty(propertyId)) {
var property = this.properties[propertyId];
fn(property, propertyId);
}
}
};
PropertyGroup.prototype.forEachChildRecursive = function (fn) {
this.forEachChild(function (child) {
fn(child);
if (child instanceof PropertyGroup) {
child.forEachChildRecursive(fn);
}
});
};
PropertyGroup.prototype._bindVisibility = function () {
_super.prototype._bindVisibility.call(this);
this._bindVisibilityRecursive();
};
PropertyGroup.prototype._bindVisibilityRecursive = function () {
this.forEachChildRecursive(function (property) {
property._bindVisibility();
});
};
PropertyGroup.prototype.isRoot = function () {
return this === this.root;
};
return PropertyGroup;
}(FormProperty));
export { PropertyGroup };