LIVR Validate if element in object is empty array - javascript

I have LIVR in a project i'm working now and is quite unclear to me how this work. I can't understand how to create new rules for custom validation.
Here's the code:
LIVR.Validator.defaultAutoTrim(true);
let validator = new LIVR.Validator({});
LIVR.Validator.registerDefaultRules({
nested_object_value() {
return function (value) {
if (!value || (value && !value.value || value === [])) {
return 'REQUIRED';
}
return '';
};
},
max_number_advancement() {
return function (value) {
if (value > 100) {
return 'MAX_NUMBER';
}
return '';
};
},
required_if_activity_present() {
return function (value, allValue) {
if (allValue.activitycycletype && !value || allValue.requestpeople === []) {
console.log(first)
return 'REQUIRED_IF_CYCLETYPE';
}
return '';
};
},
});
And this is how its used:
validationForm = () => {
const { formValue, updateErrors } = this.props;
const validData = validator.validate(formValue);
console.log(formValue)
if (!validData) {
const errorsValidator = validator.getErrors();
if (errorsValidator && Object.keys(errorsValidator).length > 0) {
const newErrors = {};
Object.keys(errorsValidator).forEach((error) => {
newErrors[error] = errorsValidator[error];
});
updateErrors(newErrors);
}
blame(t('validation-error'));
return false;
}
updateErrors({});
return true;
}
Opening the form with this validation in the app, seems to call only the last method required_if_activity_present().
What i expect here is that i can create a new method inside registerDefaultRules(), that is a LIVR method, like this:
LIVR.Validator.registerDefaultRules({
re quired_not_empty() {
return function (value) {
if (!value) {
return 'REQUIRED';
}
return '';
};
},
... //other methods
}
but seems not working, the newer method is not being called at all by validator.validate()
Anyone know how to create a new rules where i can check if an element inside the object that has to be validate is an empty array?
Because seems that LIVR doesn't return a validation error in this case, but only on empty string and null values.
Thanks in advance

Related

Vue reactivity is always one step behind

I have the following setup:
A type StringMap which I want to work like Map<> but since I'm using vue2, Map<> reactivity is not possible and I've tried to do it myself via an Array:
import Vue from "vue";
export default class StringMap {
entries: Array<[string, number]>;
constructor(data?: Record<string, number>) {
Vue.set(this, "entries", data ? Object.keys(data).map((key) => [key, data[key]]) : []);
}
get(key: string): number {
return this.entries.find((e) => e[0] === key)?.[1];
}
set(key: string, value: number): this {
const entry = this.entries.find((e) => e[0] === key);
if (entry) {
Vue.set(entry, 1, value);
}
else {
this.entries.push([key, value]);
}
return this;
}
has(key: string): boolean {
return this.entries.some((e, idx, arr) => e[0] === key);
}
delete(key: string): boolean {
const idx = this.entries.findIndex((e, idx, obj) => e[0] === key);
if (idx != -1) {
this.entries.splice(idx, 1);
}
return idx != -1;
}
clear(): void {
Vue.set(this, "entries", []);
}
}
In my Vue-Template, I have an input-field that listens to the #change method and calls calculateTotals()
<input :id="'viewModel.phasenChangeRequests[0].ppmProjektPhaseResource[' + index +'].personalInternPlanFach_PT'"
v-model="viewModel.phasenChangeRequests[0].ppmProjektPhaseResource[index].personalInternPlanFach_PT"
class="form-control"
asp-horizontal="true"
#change="calculateTotals('totalPersonalInternPlanFach_PT')"/>
And the calculateTotals is just looping over the data and summing the fields:
calculateTotals(key: string = null) {
if (this.type === "PhasenCrs") {
let totalPersonalInternPlanFachPt = 0;
for (let year = this.startyear; year < this.startyear + 5; year++) {
const phasen = this.viewModel.phasenChangeRequests;
phasen.forEach((phase) => {
var ressourcenOfYear = phase.ppmProjektPhaseResource.filter(x => x.resourceYear === year)[0];
totalPersonalInternPlanFachPt += parseFloat(ressourcenOfYear.personalInternPlanFach_PT);
});
}
if (key === null) {
console.log(`Key 'totalPersonalInternPlanFach_PT' doesn't exist yet, set it to: ${totalPersonalInternPlanFachPt}`);
this.totals2.set("totalPersonalInternPlanFach_PT", totalPersonalInternPlanFachPt);
} else {
switch (key) {
case 'totalPersonalInternPlanFach_PT':
{
console.log(`set totalPersonalInternPlanFach_PT: ${totalPersonalInternPlanFachPt}`);
this.totals2.set("totalPersonalInternPlanFach_PT", totalPersonalInternPlanFachPt);
}
}
}
}
}
totals2 is a StringMap that is initialized in the created() method:
totals2: StringMap;
async created() {
this.startyear = parseInt(moment(this.startdate, "DD.MM.YYYY").format("YYYY"));
this.projekt = JSON.parse(this.projektjson);
this.totals2 = new StringMap();
await Axios.get(this.url)
.then(res => {
this.viewModel = res.data;
})
.then(() => {
this.calculateTotals();
});
}
When I run it, it initially looks like this:
So as you can see, all fields for each year are summed correctly.
When I now change the value of 2021, the following happens:
But in the console, I can see that the total was calculated correctly:
When I now change the value back to the initial value, it shows this:
So that the previous change is now reflected in the total field but the console is showing the correct result again.
It seems that the value in the view is always one tick behind the real value...
Why is this happening?
Thanks in advance

Double for loop without mutating prop, VUE3

I have a 'data' props which say looks like this:
data = [
{
"label":"gender",
"options":[
{"text":"m","value":0},
{"text":"f","value":1},
{"text":"x", "value":null}
]
},
{
"label":"age",
"options":[
{"text":"<30", "value":0},
{"text":"<50","value":1},
{"text":">50","value":3}
]
}
]
In a computed property I want to have a new array which looks exactly like the data prop, with the difference that - for the sake of example let's say - I want to multiply the value in the options array by 2. In plain js I did this before, like this:
data.forEach(item => {
item.options.forEach(option => {
if (option.value !== null && option.value !== 0) {
option.value *= 2;
}
})
});
Now I'm trying to do this in a computed property, with .map(), so it doesn't mutate my data props, but I cant figure out how.
computed: {
doubledValues() {
var array = this.data.map((item) => {
//...
item.options.map((option) => {
//... option.value * 2;
});
});
return array;
}
}
you can use map() method, like so:
computed: {
doubledValues() {
return this.data.map(item => ({...item, options: item.options.map(obj => {
return (obj.value != null) ? { ...obj, value: obj.value * 2 } : { ...obj }
})})
);
}
}
Just copy objects/arrays. It will be something like that
computed: {
doubledValues() {
return this.data.map((item) => {
const resultItem = {...item};
resultItem.options = item.options.map((option) => {
const copyOption = {...option};
if (copyOption.value !== null && copyOption.value !== 0) {
copyOption.value *= 2;
}
return copyOption;
});
return resultItem;
});
}
}

Validate Duplicate Data Entry in Array - JavaScript

My problem is that I want to insert values that are not repeated when doing a push
This is my code :
addAddress: function() {
this.insertAddresses.Adress = this.address_address
this.insertAddresses.State = this.selectedStateAddress
this.insertAddresses.City = this.selectedCityAddress
if(this.insertAddresses.Adress !== "" && this.insertAddresses.State !== null && this.insertAddresses.City !== null) {
let copia = Object.assign({}, this.insertAddresses);
this.addresses.push(copia)
}
else
{
this.$message.error('Not enough data to add');
return
}
},
When adding a new element to my object, it returns the following.
When I press the add button again, it adds the same values again, I want to perform a validation so that the data is not the same. How could I perform this validation in the correct way?
Verify that the item doesn't already exist in the array before inserting.
You can search the array using Array.prototype.find:
export default {
methods: {
addAddress() {
const newItem = {
Address: this.address_address,
State: this.selectedStateAddress,
City: this.selectedCityAddress
}
this.insertItem(newItem)
},
insertItem(item) {
const existingItem = this.addresses.find(a => {
return
a.State === item.State
&& a.City === item.City
&& a.Address === item.Address
})
if (!existingItem) {
this.addresses.push(item)
}
}
}
}
On the other hand, if your app requires better performance (e.g., there are many addresses), you could save a separate dictonary to track whether the address already exists:
export default {
data() {
return {
seenAddresses: {}
}
},
methods: {
insertItem(item) {
const { Address, State, City } = item
const key = JSON.stringify({ Address, State, City })
const seen = this.seenAddresses[key]
if (!seen) {
this.seenAddresses[key] = item
this.addresses.push(item)
}
}
}
}
demo
check it:
let filter= this.addresses.find(x=> this.insertAddresses.State==x.State)
if (filter==null) {
this.$message.error('your message');
}
OR FILTER ALL
let filter= this.addresses.find(x=> this.insertAddresses.Adress==x.Adress && this.insertAddresses.State==x.State && this.insertAddresses.City==x.City)
if (filter==null) {
this.$message.error('your message');
}
``

JavaScript Proxy not working properly on ie11

I am building a simple validation library and I need to use Proxy because I want to accept custom validation rules as chain object. I build something and its works properly on modern browsers but not works on IE11, I tried with proxy-polyfill but its also not work properly. My proxy code is below.
function contextProxy(context) {
return new Proxy(context, {
get(obj, prop) {
if (prop in obj) {
return obj[prop];
}
const newContext = contextProxy(context._clone());
if (definedRules.hasOwnProperty(prop)) {
return newContext._takeRule(definedRules[prop]);
}
if (customRules.hasOwnProperty(prop)) {
return newContext._takeRule(customRules[prop]);
}
},
});
}
And I use that proxy;
function validationL() {
return contextProxy(new ValidationLContext());
}
And I have definedRules object;
const definedRules = {
numeric: function () {
return function (text) {
return /^\d+$/.test(text);
};
},
lowercase: function () {
return function (text) {
return /^([a-z]+\s*)+$/.test(text);
};
},
uppercase: function () {
return function (text) {
return /^([A-Z]+\s*)+$/.test(text);
};
},
minLength: function (min) {
return function (text) {
return text.length >= min;
};
},
maxLength: function (max) {
return function (text) {
return text.length <= max;
};
},
alphaNumeric: function () {
return function (text) {
return /^([a-zA-Z0-9 _-]+)$/i.test(text);
};
},
specialChars: function () {
return function (text) {
return !/^([a-zA-Z0-9 _-]+)$/i.test(text);
};
},
email: function () {
return function (text) {
return /^([a-zA-Z0-9_.+-])+\#(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(
text
);
};
}
};
ValidationLContext.js
function ValidationLContext(isNot = false, chain = []) {
this.chain = chain;
this.isNot = isNot;
}
ValidationLContext.prototype.not = function () {
this.isNot = true;
return this;
};
ValidationLContext.prototype._takeRule = function (ruleFn) {
return (...args) => {
this.chain.push({ fn: ruleFn.apply(this, args), isNot: this.isNot });
if (this.isNot) {
this.isNot = false;
}
return this;
};
};
ValidationLContext.prototype.validate = function (text) {
return this.chain.every((c) =>
c.isNot ? !c.fn.call(this, text) : c.fn.call(this, text)
);
};
ValidationLContext.prototype._clone = function () {
return new ValidationLContext(this.isNot, this.chain);
};
export default ValidationLContext;
So library usage like this;
validationL().numeric().minLength(3).validate("123");
validationL().not().numeric().minLength(3).validate("123");
I can use like above on modern browsers like Chrome but when I try on IE11 only not() function works so only objects functions can work.
Can anyone help me with this.

Undefined for firebase subscribe

I need to return array of items to display it on HomePage
I tried to modify the code, but nothing works. I feel like I need a slight change for my code
getItems(segmentType): any {
return this.db.collection('items', ref => ref.where('type', '==',
segmentType)).valueChanges();
}
getItemsBySearchQuery(segmentType, queryText): any[] {
this.getItems(segmentType).subscribe(items => {
this.itemsContainer = items;
this.filteredItems = this.itemsContainer.filter((v) => {
if (v.title && queryText) {
if (v.title.toLowerCase().indexOf(queryText.toLowerCase()) > -1) {
return true;
}
return false;
}
});
});
//TODO: THIS IS STILL UNDEFINED
return this.filteredItems;
}
Ion-List with filtered elements, but I have "undefined", because code returns the array too early

Categories