Conditional check with AND and OR is failing - if-statement

I am trying to combine few conditional check
package main
import (
"fmt"
"reflect"
)
type ActionType string
const (
VNFHealthCheck ActionType = "vnf-health-check"
CollectAlaramAddToReport ActionType = "write-initial-report"
CollectResourcesAddCounters ActionType = "abc"
)
func main() {
var action, operationType interface{}
action = nil
operationType = "vnf-health-check"
if operationType == string(VNFHealthCheck) && action != nil && action.(ActionType) == CollectAlaramAddToReport {
fmt.Println("Type is ", reflect.TypeOf(action))
}
}
The above code does not print anything as action != nil check fails.
But when if condition changes to
if operationType == string(VNFHealthCheck) && action != nil && action.(ActionType) == CollectAlaramAddToReport || action.(ActionType) == CollectResourcesAddCounters {
fmt.Println("Hello, playground", reflect.TypeOf(action))
}
Panic is seen with message
panic: interface conversion: interface {} is nil, not main.ActionType
If condition check works fine after adding () around OR condition
if operationType == string(VNFHealthCheck) && action != nil && (action.(ActionType) == CollectAlaramAddToReport || action.(ActionType) == CollectResourcesAddCounters) {
fmt.Println("Hello, playground", reflect.TypeOf(action))
}
What could be cause of the behavior.? I couldn't find any explanation.

the && has higher precedence than ||
in the first condition,
operationType == string(VNFHealthCheck) && action != nil && action.(ActionType) == CollectAlaramAddToReport || action.(ActionType) == CollectResourcesAddCounters
cause action is nil, the condition becomes false || action.(ActionType) == CollectResourcesAddCounters. the nil cast trigger the panic
the second condition becomes false && (action.(ActionType) == CollectAlaramAddToReport || action.(ActionType) == CollectResourcesAddCounters). cause the false short circuit the expression, the cast won't be executed.

See the operator precedence section of the specification. The && operator has higher precedence than ||. The parentheses are required to get the grouping you intended.
A type assertion is not needed when comparing a value to an interface{}. If action is one of the specified values, then it follows that action != nil. Using these observations, simplify the code to:
if operationType == string(VNFHealthCheck) && (action == CollectAlaramAddToReport || action == CollectResourcesAddCounters) {
fmt.Printf("Hello, playground %T\n", action)
}

Related

How can I write if-else conditions in cypress according to element's value?

How can I run this function, according to the value change of element with if-condition?
assertSwitch(){
cy.get('[data-test="form-switch"]').invoke('attr','value').then(($switchOnOff) =>{
if($switchOnOff == true){
cy.isContain('.item-undefined-switch[data-test="item-undefined-email"]', 'true')
}else{
cy.isContain('.item-undefined-switch[data-test="item-undefined-email"]', 'false')
}
})
}
You can do something like this:
cy.get('[data-test="form-switch"]').then(($ele) => {
if ($ele.attr('val') == 'true') {
cy.get('button[data-test="form-switch-input"]').should(
'have.attr',
'aria-checked',
'true'
)
//Add something here
} else {
cy.get('button[data-test="form-switch-input"]').should(
'have.attr',
'aria-checked',
'false'
)
//Add something here
}
})
The problem is both switches have the same data-test, so Cypress starts to get confused
cy.get('[data-test="form-switch"]')
.eq(0) // pick one
.invoke('attr','aria-checked') // this attr indicates checked state
.then(($switchOnOff) => {
if($switchOnOff === 'true') { // note adjustments here
cy.isContain('.item-undefined-switch[data-test="item-undefined-email"]', 'true')
} else {
cy.isContain('.item-undefined-switch[data-test="item-undefined-email"]', 'false')
}
})
Or all switches
cy.get('[data-test="form-switch"]')
.each(($switchOnOff) => {
const value = $switchOnOff.attr('aria-checked')
cy.isContain('.item-undefined-switch[data-test="item-undefined-email"]', value)
})

Force user to type a regex on input

I have been trying to do a regexp to force the user to just type what I want in the input and NOT display it in the input field. I have try use many events, but the event type it on the input field and have to make an extra validation or found some errors using the code. Never found the correct event.
this is my html file:
<input [(ngModel)]="someModel" (keydown)="validate($event);">
this is my component
validateRegex(event: any) {
let regexp = new RegExp(/^([0-9][0-9]?)(\.([0-9][0-9]?)?)?$/);
let keyPress = event.key;
if(!event.ctrlKey && (event.altKey || event.shiftKey)) {
event.preventDefault();
event.stopPropagation();
}
if(!event.ctrlKey && keyPress.length < 2) { //Make sure it just press 1 digit, avoid stuff like "backspace"
if(keyPress == '0' || keyPress == '1' || keyPress == '2' || keyPress == '3' || keyPress == '4' || keyPress == '5'
|| keyPress == '6' || keyPress == '7' || keyPress == '8' || keyPress == '9' || keyPress == '.' ) {
let test = this.someModel ? this.someModel.toString() + event.key: event.key;
if (!regexp.test(test)) {
event.preventDefault();
event.stopPropagation();
}
} else {
event.preventDefault();
event.stopPropagation();
}
}
}
Now this validate the user to insert just decimals with 2 digits after and before the dot, also doesn't allow the dot to be on his own. The problem with this code, is that if the user types '99.' and then clicks/arrows backwards to the first 9, he will be able to insert a 9 at the beginning, breaking the regular expression. event just only got the key inserted, not sure where is going to be inserted.
If I don't use keydown/keypress the display input will change already, the validation will be made, but the UI will change. In keydown, the UI is still not changed. I don't want to block the user from moving around the input neither
Now yes, I could solve this problem using a mask, but the library mask I got have problems and have some errors too. Shamefully I cannot use any other.
Can this be solve with the proper event or asking for the altered value somehow on the keydown or It is possible to create my own mask and solve this?
html
<input #input [ngModel]="value" (ngModelChange)="onChange($event);">
ts
import { Component, ViewChild } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
value = '0';
#ViewChild('input', { static: false }) input;
onChange(value: string) {
let regexp = /^([0-9][0-9]?)(\.([0-9][0-9]?)?)?$/;
if (!value) {
this.value = '';
}
if (!regexp.test(value)) {
this.input.nativeElement.value = this.value
} else {
this.value = value;
}
}
}
https://stackblitz.com/edit/angular-phfkcy?file=src%2Fapp%2Fapp.component.html

How to enter only a number like this XX.XXX,XX (currency)in the input while Im typing?(Angular)

How can I type only a number in this format xx.xxx,xx(currency). If I type letters, characters and other special characters i would like to be stopped. I attached the code. I would appreciate any help. Thanks!
import { Directive, HostListener, ElementRef, Input } from '#angular/core';
#Directive({
selector: '[currencyNumeric]'
})
export class CurrencyDirective {
regexStr = 'reg exp for xx.xxx,xx';
#Input() currencyNumeric: boolean;
constructor(private el: ElementRef) { }
#HostListener('keypress', ['$event']) onKeyPress(event) {
return new RegExp(this.regexStr).test(event.key);
}
#HostListener('paste', ['$event']) blockPaste(event: KeyboardEvent) {
this.validateFields(event);
}
validateFields(event) {
setTimeout(() => {
this.el.nativeElement.value = this.el.nativeElement.value.replace(/currency reg exp for XX.XXX,XX/g, '').replace(/\s/g, '');
event.preventDefault();
}, 100)
}
}
<input type="text" currencyNumeric >
You can use this code
add this directive
import { Directive, HostListener, ElementRef, OnInit } from '#angular/core';
import {MycurrencyPipe} from './mycurrency.pipe';
#Directive({
selector: '[appMycurrency]',
providers:[MycurrencyPipe]
})
export class MycurrencyDirective implements OnInit{
private el: any;
constructor(
private elementRef:ElementRef,
private formatcurrencypipe:MycurrencyPipe
) {
this.el = this.elementRef.nativeElement;
}
ngOnInit(){
this.el.value = this.formatcurrencypipe.transform(this.el.value);
}
#HostListener("focus",["$event.target.value","$event"])
onFocus(value,event) {
this.el.value = this.formatcurrencypipe.parse(value); // opossite of transform
if(event.which== 9)
{
return false;
}
this.el.select();
}
#HostListener("blur", ["$event.target.value"])
onBlur(value) {
this.el.value = this.formatcurrencypipe.transform(value);
}
#HostListener('keydown', ['$event']) onKeyDown(event) {
let e = <KeyboardEvent> event;
if ([46, 8, 9, 27, 13, 110, 190].indexOf(e.keyCode) !== -1 ||
// Allow: Ctrl+A
(e.keyCode === 65 && (e.ctrlKey || e.metaKey)) ||
// Allow: Ctrl+C
(e.keyCode === 67 && (e.ctrlKey || e.metaKey)) ||
// Allow: Ctrl+V
(e.keyCode === 86 && (e.ctrlKey || e.metaKey)) ||
// Allow: Ctrl+X
(e.keyCode === 88 && (e.ctrlKey || e.metaKey)) ||
// Allow: home, end, left, right
(e.keyCode >= 35 && e.keyCode <= 39)) {
// let it happen, don't do anything
return;
}
// Ensure that it is a number and stop the keypress
if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
e.preventDefault();
}
}
}
the directive needs this Pipe
import { Pipe, PipeTransform } from '#angular/core';
const padding = "000000";
#Pipe({
name: 'mycurrency'
})
export class MycurrencyPipe implements PipeTransform {
private prefix: string;
private decimal_separator:string;
private thousands_separator:string;
private suffix:string;
constructor(){
this.prefix='$ ';
this.suffix='';
this.decimal_separator='.';
this.thousands_separator = ',';
}
transform(value: string, fractionSize:number = 0 ): string {
if(parseFloat(value) % 1 != 0)
{
fractionSize = 2;
}
let [ integer, fraction = ""] = (parseFloat(value).toString() || "").toString().split(".");
fraction = fractionSize > 0
? this.decimal_separator + (fraction+padding).substring(0, fractionSize) : "";
integer = integer.replace(/\B(?=(\d{3})+(?!\d))/g, this.thousands_separator);
if(isNaN(parseFloat(integer)))
{
integer = "0";
}
return this.prefix + integer + fraction + this.suffix;
}
parse(value: string, fractionSize: number = 2): string {
let [ integer, fraction = "" ] = (value || "").replace(this.prefix, "")
.replace(this.suffix, "")
.split(this.decimal_separator);
integer = integer.replace(new RegExp(this.thousands_separator, "g"), "");
fraction = parseInt(fraction, 10) > 0 && fractionSize > 0
? this.decimal_separator + (fraction + padding).substring(0, fractionSize)
: "";
return integer + fraction;
}
}
and you can use it like <input appMycurrency type="text" />
don't forget to add MycurrencyPipe, MycurrencyDirective in declarations on NgModule
full app is here here
Use capturing groups (by index) in Regular Expressions. like this:
this.el.nativeElement.value = this.el.nativeElement.value.replace(/(\d{2})(\d{3})(\d{2})/, "$1.$2,$3")

FluentValidation: how to simplify this code?

I'm using FluentValidation library to create validators like this:
Please any one help me to simplify this part of code?
private bool UniqueSimNo(string simNo)
{
MyContext _db = new MyContext();
Sim s = _db.Sims.Where(x => x.SimNo.ToLower() == simNo.ToLower()).SingleOrDefault();
var sim = _db.Sims.Where(x => x.SimNo.ToLower() == s.SimNo.ToLower()).Where(x => x.Id != s.Id).FirstOrDefault();
if (sim == null) return true;
return false;
}
Well, your code doesn't make sense if you don't pass an id as parameter to your method.
I guess you wanna use the same validator for a new item (id = 0) and an existing (id !=0).
This line doesn't do what you think it is doing after your SingleOrDefault test, as SingleOrDefault would raise an exception if there was more than one item with same SimNo :
var sim = _db.Sims.Where(x => x.SimNo.ToLower() == s.SimNo.ToLower()).Where(x => x.Id != s.Id).FirstOrDefault();
So I would do
private bool UniqueSimNo(string simNo, int id = 0) {
var _db = new MYContext());
return !_db.Sims.Any(x => x.Id != id && x.simNo.ToLower() == simNo.ToLower());
}

Directive to allow decimal numbers with only 1 decimal point

I have an angular application where an input field should allow only positive numbers with one decimal point. In my directive I am replacing anything other than 0-9 and '.'.But currently my application is accepting multiple decimal values.
It should accept:
0.5
0.56
Not
0.5.5 or 0..5
PFB the code:
link: function (scope, element, attrs, modelCtrl) {
modelCtrl.$parsers.push(function (inputValue) {
// this next if is necessary for when using ng-required on your input.
// In such cases, when a letter is typed first, this parser will be called
// again, and the 2nd time, the value will be undefined
if (inputValue === undefined) {
return '';
}
var transformedInput = inputValue.replace(/[^0-9\.]/g, '');
if (transformedInput !== inputValue) {
modelCtrl.$setViewValue(transformedInput);
modelCtrl.$render();
}
return transformedInput;
});
}
This question might seem ignorant but I have tried all the solutions provided before this but changing my regular expression according to the same doesn't seem to work. It accepts right now multiple '.'.
Thanks in advance.
Here is fiddle http://jsfiddle.net/oora0t93/ check it:-
app.directive('inputPrice', function () {
return {
restrict: 'EA',
template: '<input name="{{inputName}}" ng-model="inputValue" />',
scope: {
inputValue: '=',
inputName: '='
},
link: function (scope) {
scope.$watch('inputValue', function(newValue,oldValue) {
if(String(newValue).indexOf(',') != -1)
scope.inputValue = String(newValue).replace(',', '.');
else {
var index_dot,
arr = String(newValue).split("");
if (arr.length === 0) return;
if (arr.length === 1 && (arr[0] == '-' || arr[0] === '.')) return;
if (arr.length === 2 && newValue === '-.') return;
if (isNaN(newValue) || ((index_dot = String(newValue).indexOf('.')) != -1 && String(newValue).length - index_dot > 3 )) {
scope.inputValue = oldValue;
}
}
});
}
};
});
I got it. I did not find a regular expression solution so did it using some javascript string manipulations. PFB the code:
var firstIndexOfDecimal = transformedInput.indexOf('.');
var lastIndexofDecimal = transformedInput.lastIndexOf(".");
if(firstIndexOfDecimal !== lastIndexofDecimal){
transformedInput = transformedInput.substr(0,lastIndexofDecimal) + transformedInput.substr(lastIndexofDecimal+1, transformedInput.length);
}
Thanks for the help.