I have the following code:
class IPHeaderComponentController extends App.Core.Domain.BaseController {
public api: ApiRule = {};
public exception: Error = null;
static $inject = ['ipService', 'loggerServices', '$scope'];
constructor(private IpService: IpService, private loggerServices: Core.Services.ILoggerServices, private $scope: angular.IScope) {
super();
Rx.Observable.fromEvent(document.getElementById('btnRule'), 'click').subscribe(() => this.add());
this.IpService.errors$.subscribe((exception: Error) => {
if (exception !== null) {
this.loggerServices.error(exception.message, exception.name);
this.exception = exception;
}
});
}
private add = () => {
this.IpService.validateRule(this.api);
if (this.exception === null) {
this.IpService.addRule(this.api.rule, this.api.source, this.api.destiny);
this.$scope.$applyAsync(() => {
this.api.rule = "";
this.api.source = "";
this.api.destiny = "";
});
} else {
this.exception = null;
}
};
}
In the component's constructor, I subscribe to an observable where form errors are sent.
this.IpService.errors$.subscribe((exception: Error) => {
if (exception !== null) {
this.loggerServices.error(exception.message, exception.name);
this.exception = exception;
}
});
If they are fixed, I have a property in the component that is called exception that is of type Error and that I initialize it to null.
this.IpService.validateRule(this.api);
if (this.exception === null) {
this.IpService.addRule(this.api.rule, this.api.source, this.api.destiny);
this.$scope.$applyAsync(() => {
this.api.rule = "";
this.api.source = "";
this.api.destiny = "";
});
} else {
this.exception = null;
}
When errors $ emits an error I check that the error is not null, if so, then I equal it (I use it as a sneak variable) that is, if it is different from null, there was an error. Then I assign it again the value null.
The service that contains all the business logic is as follows:
namespace App.Service.Services {
import Subject = Rx.Subject;
import ApiRule = App.Apis.Saa.Domain.ApiRule;
import Observable = Rx.Observable;
import BehaviorSubject = Rx.BehaviorSubject;
type ApiRulesOperation = (rules: ApiRule[]) => ApiRule[];
const initialRules: ApiRule[] = JSON.parse(sessionStorage.getItem('angular-rxjs-rules')) || [];
export class IpService {
public rules$: Observable<ApiRule[]>;
public errors$: Subject<Error> = new Subject<Error>();
private update$: BehaviorSubject<ApiRulesOperation> = new BehaviorSubject<ApiRulesOperation>((rules: ApiRule[]) => rules);
private validateRule$: Subject<ApiRule> = new Subject<ApiRule>();
private createRule$: Subject<ApiRule> = new Subject<ApiRule>();
private modifyRule$: Subject<ApiRule> = new Subject<ApiRule>();
private removeRule$: Subject<string> = new Subject<string>();
private ruleRepeatedValidate$: Subject<ApiRule> = new Subject<ApiRule>();
private ipStartFormatValidate$: Subject<ApiRule> = new Subject<ApiRule>();
private ipEndFormatValidate$: Subject<ApiRule> = new Subject<ApiRule>();
private create$: Subject<ApiRule> = new Subject<ApiRule>();
private modify$: Subject<ApiRule> = new Subject<ApiRule>();
private remove$: Subject<string> = new Subject<string>();
constructor() {
this.rules$ = this.update$
.scan((rules: ApiRule[], operation: ApiRulesOperation) => operation(rules), initialRules)
.shareReplay(1);
this.rules$.forEach(rules => sessionStorage.setItem('angular-rxjs-rules', JSON.stringify(rules)));
this.ruleRepeatedValidate$.map((rule: ApiRule): Error => {
let exception: Error = null;
const search = initialRules.find(t => t.rule === rule.rule);
if (search !== undefined) {
exception = {
name: "Regla repetida",
message: "No se puede repetir el nombre de la regla."
};
}
return exception;
}).subscribe(this.errors$);
this.ipStartFormatValidate$.map((rule: ApiRule): Error => {
let exception: Error = null;
if (!(/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(rule.source))) {
exception = {
name: "IP Inicial",
message: "La IP inicial no tiene el formato correcto."
};
}
return exception;
}).subscribe(this.errors$);
this.ipEndFormatValidate$.map((rule: ApiRule): Error => {
let exception: Error = null;
console.log("Destiny: ", rule.destiny);
if (!(/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(rule.destiny))) {
exception = {
name: "IP Final",
message: "La IP final no tiene el formato correcto."
};
}
return exception;
}).subscribe(this.errors$);
this.create$.map((rule: ApiRule): ApiRulesOperation => {
return (rules: ApiRule[]) => {
const search = rules.find(t => t.rule === rule.rule);
if (search !== undefined) {
return rules;
} else {
return rules.concat(rule);
}
}
});
this.modify$
.map((rule: ApiRule): ApiRulesOperation => {
return (rules: ApiRule[]) => {
const modifyRule = rules.find(t => t.rule === rule.rule);
modifyRule.rule = rule.rule;
modifyRule.destiny = rule.destiny;
modifyRule.source = rule.source;
return rules;
};
})
.subscribe(this.update$);
this.remove$
.map((name: string): ApiRulesOperation => (rules: ApiRule[]) => rules.filter(rule => rule.rule !== name))
.subscribe(this.update$);
this.createRule$
.subscribe(this.create$);
this.validateRule$.subscribe(this.ruleRepeatedValidate$);
this.validateRule$.subscribe(this.ipStartFormatValidate$);
this.validateRule$.subscribe(this.ipEndFormatValidate$);
this.modifyRule$
.subscribe(this.modify$);
this.removeRule$
.subscribe(this.remove$);
}
public addRule = (rule: string, source: string, destiny: string): void => {
let newRule: ApiRule = {
rule: rule,
source: source,
destiny: destiny
};
this.createRule$.onNext(newRule);
};
public modifyRule(rule: ApiRule): void {
this.modifyRule$.onNext(rule);
}
public removeRule(name: string): void {
this.removeRule$.onNext(name);
}
public validateRule(rule: ApiRule) {
this.validateRule$.onNext(rule);
}
}
angular
.module("app.service")
.service("ipService", IpService);}
These are the ones that are in charge of validating the rules:
this.ruleRepeatedValidate$.map((rule: ApiRule): Error => {
let exception: Error = null;
const search = initialRules.find(t => t.rule === rule.rule);
if (search !== undefined) {
exception = {
name: "Regla repetida",
message: "No se puede repetir el nombre de la regla."
};
}
return exception;
}).subscribe(this.errors$);
this.ipStartFormatValidate$.map((rule: ApiRule): Error => {
let exception: Error = null;
if (!(/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(rule.source))) {
exception = {
name: "IP Inicial",
message: "La IP inicial no tiene el formato correcto."
};
}
return exception;
}).subscribe(this.errors$);
this.ipEndFormatValidate$.map((rule: ApiRule): Error => {
let exception: Error = null;
console.log("Destiny: ", rule.destiny);
if (!(/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(rule.destiny))) {
exception = {
name: "IP Final",
message: "La IP final no tiene el formato correcto."
};
}
return exception;
}).subscribe(this.errors$);
The way I'm using works correctly, but I do not think it's the right one. Can someone tell me another way to validate the data? What I'm looking for is to remove the snooping variable (exception) and use a more appropriate way for it to be the flow that indicates whether to continue adding or not adding the rule.