Vue.js - Element UI - get the state of form validation - vue.js

Steps to reproduce
The recurrence link is this: https://stackblitz.com/edit/typescript-vuejs-element-3kko7a
password input 2
username input 11
Change username to 2// should be able to submit, but not
Expected: formvalid = true
Validate Code here:
checkForm() {
// console.log('validate runs');
// #ts-ignore
const fields = this.$refs.ruleForm.fields;
if (fields.find((f) => f.validateState === 'validating')) {
setTimeout(() => {
this.checkForm();
}, 100);
}
this.formValid = fields.reduce((acc, f) => {
const valid = (f.isRequired && f.validateState === 'success');
const notErroring = (!f.isRequired && f.validateState !== 'error');
return acc && (valid || notErroring);
}, true);
console.log('valid:', this.$data.formValid);
}

Basically you watch ruleForm - so everytime ruleForm changes you trigger checkform - but your validtor triggers on blur after you set ruleForm so you first test then turn valid. change this into a getter:
get formValid(){
const fields = this.$refs.ruleForm.fields || [];
if (fields.find((f) => f.validateState === 'validating')) {
setTimeout(() => {
this.checkForm();
}, 100);
}
return fields.reduce((acc, f) => {
const valid = (f.isRequired && f.validateState === 'success');
const notErroring = (!f.isRequired && f.validateState !== 'error');
return acc && (valid || notErroring);
}, fields.length > 0);
}

Related

In React-native i'm using 'sharingan-rn-modal-dropdown'; Dropdown in form for add and edit data but selected values not getting reflected in dropdown

what exactly is happening is when i select the delivery service onChangeService i'm setting the next dropdown i.e. carrier's list.Also i'm setting the selected carrier as per the service.But all the time value is getting set correctly in {this.state.selectedCarrierName} but still i can show its label only.lists contain label an value pair
async onChangeService(value) {
//{ ...this.props.deliveryOptionsValue, selected: value.value === value }
this.setState({ newCarrierList: [], selectedCarrierName: '', selectedCararierName: '' });
const priceDeliveryService = this.props.orderDetailsDTO.priceDeliveryServiceDTOs;
console.log("carriers", JSON.stringify(this.props.carriers));
var newList = [];
var carrier = '';
await priceDeliveryService.forEach(m => {
console.log("compare", m.serviceId === value.id);
if (m.serviceId === value.id) {
console.log("carrier", JSON.stringify(this.props.carriers));
let l = this.props.orderDetailsDTO.carriers.filter(n => n.id === m.carrierId);
console.log("l", l);
if (l !== undefined) {
// / orderList: [...this.state.orderList, ...content]
// this.setState({ newCarrierList: [...this.state.newCarrierList, ...l[0]] });
newList.push(l[0]);
console.log("defa", newList);
if (m.defaultCarrierService) {
this.setState({ selectedCarrier: l[0], selectedCarrierName: l[0].name });
carrier = l[0].name;
} else {
this.setState({ selectedCarrier: newList[0], selectedCarrierName: newList[0].name });
carrier = newList[0].name;
}
}
}
});
const list = newList.map(item => ({
label: item.name,
value: item
}));
this.setState({ newCarrierListValue: list, newCarrierList: newList })
console.log("newCarrierListValue", list);
console.log("newCarrierList", newList);
// console.log("carrier service", p.carrierName, value.id);
const carrierServices = this.props.orderDetailsDTO.carrierServiceDTO;
console.log(carrierServices.length);
const pi = await this.setCarrierService(carrierServices, value, carrier);
// let pi;
// for (let i = 0; i < carrierServices.length; i++) {
// console.log("if", carrierServices[i].cdlServiceId == value.id, carrierServices[i].carrierName === carrier)
// if (carrierServices[i].cdlServiceId == value.id && carrierServices[i].carrierName === carrier) {
// console.log("mathced data", carrierServices[i]);
// pi = carrierServices[i];
// console.log(pi);
// break;
// }
// }
this.setState({ carrierService: pi.serviceName, carrierServices: carrierServices });
console.log(pi.serviceName);
}
<Dropdown required
label="Select delivery option"
data={this.props.deliveryOptionsValue}
// enableSearch
defaultValue={1}
value={this.state.selectedDeliveryOptionName}
onChange={(value) => {
console.log(" change value", value);
this.setState({ selectedDeliveryOptionName: value.name, selectedDeliveryOption: value, deliveryOptionError: false, });
this.onChangeService(value);
}} />
<Dropdown
required
label="Select a carrier"
data={this.state.newCarrierListValue}
// selectedValue={this.state.selectedCarrierName}
value={this.state.selectedCarrierName}
onChange={value => {
// console.log("value", value);
this.setState({ selectedCarrierName: value.name, selectedCarrier: value });
this.onChangeCarrier(value, this.state.selectedDeliveryOption);
}} />

Issue with react-native FlatList rendering data when updating array of objects maintained in redux

I'm loading a dynamic form in a FlatList. I'm supposed to add few rows with UI elements such as TextInput, checkbox, etc. based on a condition. For example, I have a dropdown, when I select a value, I have to add a row with a button and remove that row when I select another value.
My issue is that whenever I select a value in the dropdown to add a row with button, FlatList is adding duplicate rows and they are not visible as objects in my array when I debug them. I'm using Redux to manage my application state and updating my array in reducers.
I have to display objects in my array in FlatList without any duplicates using Redux for state management.
Code:
<FlatList
key={Math.floor(Math.random())}
ref={(ref) => { this.flatListRef = ref; }}
data={this.state.mainArray}
renderItem={this._renderItem}
keyExtractor={({ item, id }) => String(id)}
extraData={this.prop}
keyboardDismissMode="on-drag"
showsVerticalScrollIndicator={false}
scrollEnabled={true}
removeClippedSubviews={false}
scrollsToTop={false}
initialNumToRender={100}
/>
componentWillReceiveProps(nextProps) {
this.setState({mainArray: nextProps.mainArray});
}
Updating array in Reducer:
case VALIDATE_DEPENDENCY: {
// adding or removing dependency questions
let dependingQues = [];
let formArrayTemp = [...state.mainArray];
let exists;
// console.log("formArrayTemp123", formArrayTemp);
if (action.item.isDependentQuestion) {
if (action.item.dependentQuestionsArray.length > 0) {
let dependent_ques = action.item.dependentQuestionsArray[0];
state.depending_questions_array.filter((obj, id) => {
if (JSON.stringify(obj.key_array) === JSON.stringify(dependent_ques.key)) {
dependingQues.push(obj);
}
});
// console.log("dependingQues123", dependingQues);
if (dependent_ques.answer === action.item.answer) {
dependingQues.map((obj, id) => {
exists = formArrayTemp.filter((res, idx) => {
if (JSON.stringify(res.key_array) === JSON.stringify(obj.key_array)) {
return res;
}
});
// console.log("exists123", exists);
if (exists.length === 0) {
formArrayTemp.splice(action.index + id + 1, 0, obj);
// console.log("mjkgthbythyhy", action.index + id + 1);
}
});
}
else {
let objIndex = formArrayTemp.findIndex(obj => JSON.stringify(obj.key_array) === JSON.stringify(dependent_ques.key));
if (objIndex !== -1) {
formArrayTemp[objIndex].answer = "";
formArrayTemp[objIndex].borderColor = "black";
formArrayTemp.splice(objIndex, 1);
// console.log("frtg6hyjukiu", formArrayTemp);
}
}
}
}
// adding or removing dependent sections
let dependentSections = [];
let tempArr = [];
let count = 0;
if (action.item.isDependent) {
if (action.item.dependentArray.length > 0) {
let dependent_section = action.item.dependentArray[0];
state.dependent_sections_array.filter((obj, id) => {
if (obj.section_id === dependent_section.section_id) {
dependentSections.push(obj);
}
});
// console.log("dependentSections123", dependentSections);
let lastIndex;
formArrayTemp.filter((res, id) => {
if (action.item.section_id === res.section_id && res.dependentArray &&
JSON.stringify(action.item.dependentArray) === JSON.stringify(res.dependentArray)) {
tempArr.push(res);
lastIndex = formArrayTemp.FindLastIndex(a => a.section_id === res.section_id);
}
});
// console.log("lastIndex123", lastIndex);
tempArr.map((obj, id) => {
if (obj.answer === obj.dependentArray[0].answer) {
count++;
}
});
if (dependent_section.answer === action.item.answer) {
dependentSections.map((obj, id) => {
if (formArrayTemp.contains(obj) === false) {
formArrayTemp.splice(lastIndex + id + 1, 0, obj);
// console.log("cfrererfre", formArrayTemp);
}
});
}
else {
let countTemp = [];
if (count === 0) {
let countTemp = [];
dependentSections.filter((res, id) => {
if (formArrayTemp.contains(res) === true) {
formArrayTemp.filter((obj, idx) => {
if (obj.section_id === res.section_id) {
obj.answer = "";
obj.borderColor = "black";
countTemp.push(obj);
}
});
}
});
let jobsUnique = Array.from(new Set(countTemp));
formArrayTemp = formArrayTemp.filter(item => !jobsUnique.includes(item));
// console.log("frefrefre123", formArrayTemp);
// return { ...state, mainArray: [...formArrayTemp] }
}
}
}
}
console.log("formArray123", formArrayTemp);
formArrayTemp.sort((a, b) => {
return a.posiiton - b.position;
});
return { ...state, mainArray: formArrayTemp }
};
Update
After researching this issue I came across this issue #24206 in GitHub. There it states:
There's a few things you aren't doing quite correctly here. Each time the render function runs you are creating a new array object for your data, so React has to rerender the entire list each time, you're renderItem function and keyExtractor function are also remade each rerender, and so the FlatList has to be rerun. You're also using the index for your key which means as soon as anything moves it will rerender everything after that point. I would recommend looking at what does/doesn't change when you rerun things (arrays, functions, object), and why the keyExtractor is important for reducing re-renders.
So I tried commenting KeyExtractor prop of FlatList and the issue got resolved. But this is causing issue in another form. How can I resolve that?

setinterval function is running infinitely

const interval = setInterval(() => {
fire.database().ref().child(getpath())
.once("value",
(snapshot) => {
let item = snapshot.val()
console.log(item)
if (item !== null) {
let array = [];
Object.
keys(item)
.forEach(i => array.push(item[i]));
setCard1(array);
}
console.log(item, "item")
if (item !== null) {
itemlen = 7 //length of object I get from valid result
//stop polling for results
console.log(itemlen, "should clear")
}
else {
console.log("polling")
}
})
}, 1000)
console.log("comingout")
if (itemlen !== 0) {
console.log("goingIn")
clearInterval(interval);
}
}, [prefVar]);
expected clearinterval to stop the setinterval function but it is running continuosly and not stopping
itemlen is getting non zero values.Is there a better way of implementing this ?
I want stop useEffect once I get valid value from db.My code inside the for setinterval selects a random path and retrieve that path only problem is that sometimes the path is empty,thus using setInterval
I would create two state items, one which keeps the interval and the other which stores itemlen, and would use another useEffect to listen on changes to itemlen, and when it is not 0, the interval should clear. Also, I would check if there is another interval running before you start another one.
const [itemlen, setItemlen] = useState(0);
const [pollingInterval, setPollingInterval] = useState(null);
useEffect(() => {
if (pollingInterval === null) {
setPollingInterval(setInterval(() => {
fire.database().ref().child(getpath())
.once("value",
(snapshot) => {
let item = snapshot.val()
console.log(item)
if (item !== null) {
let array = [];
Object.
keys(item)
.forEach(i => array.push(item[i]));
setCard1(array);
}
console.log(item, "item")
if (item !== null) {
setItemlen(7);
console.log("should clear")
} else {
console.log("polling")
}
})
}, 1000));
}
}, [prefVar]);
useEffect(() => {
if (itemlen !== 0 && pollingInterval !== null) {
clearInterval(pollingInterval);
setPollingInterval(null);
}
}, [itemlen])

React Native SectionList (title, data) - Search in the data field

I am trying to build Search function in SectionList. I have search inside the 'data' (second field) and not inside 'title' but I am not able to make it work.
My Data is about the Flat / resident details of an Apartment -
sectiondata =
[{"title":"GROUND FLOOR",
"data":[
{"id":"48","res_type":"owner","user_name":"Ashwani","flat_id":"1","flat_name":"001","floor_no":"GROUND FLOOR","floor_int":"0","signal_player_id":"aa","user_phone":"98855550"},
{"id":"49","res_type":"owner","user_name":"Rahul","flat_id":"2","flat_name":"002","floor_no":"GROUND FLOOR","floor_int":"0","signal_player_id":"aa","user_phone":"999999"}
]
}]
I am trying something like this but it is not working.
searchFilterFunction = (text) => {
let search = text.toLowerCase();
this.setState({
check: this.state.sectiondata.filter(
obj => obj.data['flat_name'].toLowerCase().includes(search))
});
}
How to filter data base on name? Please assist here.
Thanks.
You can try to search like this:
onChangeText(text) {
if (text.trim().length > 0) {
var temp = []
sectiondata.map((item) => {
var dataItem = {};
var brandData = [];
item.data.map((searchItem) => {
let flatName = searchItem.flat_name
if (flatName.match(text)) {
brandData.push(searchItem);
}
})
if (brandData.length > 0) {
} else {
return null;
}
dataItem.brandData = brandData;
temp.push(dataItem);
this.setState({
sectiondata: temp
})
})
} else {
this.setState({
sectiondata: this.state.tempData
})
}
}
searchFilterFunction(text) {
if( text == undefined || text == '') {
this.setState({
sectiondata: this.arrayholder
})
return;
}
if (text.trim().length > 0) {
var temp = []
this.state.sectiondata.map((item) => {
var dataItem = {};
var title = item.title;
var brandData = [];
item.data.map((searchItem) => {
let flatName = searchItem.flat_name
if (flatName.match(text)) {
brandData.push(searchItem);
}
})
if (brandData.length > 0) {
} else {
return null;
}
dataItem.title = title;
dataItem.data = brandData;
temp.push(dataItem);
this.setState({
sectiondata: temp
})
})

Behavior Subject unsubscribe refactor

This can't be the only way to unsub Behavior Subjects :
maxSub;
fromSub;
toSub;
pageNumberSub;
originalMaxSub;
selectionSub;
selectionOfInterestSub;
constructor(private store: StoreService) {}
ngAfterContentChecked(){
this.maxSub = this.store.max$.subscribe((max) => {
if(max !== null && max !== undefined){
this.max = max;
this.maxPages = Math.floor(this.max / Variables.to);
this.pages = Array.from(Array(this.maxPages), (x, i) => i + 1);
}
}, (error) => console.log(error), () => {});
this.fromSub = this.store.from$.subscribe((from) => {
if(from !== null && from !== undefined) {this.from = from; this.split = this.to - (this.from - 1)}
}, (error) => console.log(error), () => {});
this.toSub = this.store.to$.subscribe((to) => {
if(to !== null && to !== undefined) {this.to = to; this.split = this.to - (this.from - 1)}
}, (error) => console.log(error), () => {});
this.pageNumberSub = this.store.pageNumber$.subscribe((pageNumber) => {
if(pageNumber !== null && pageNumber !== undefined) {this.page = pageNumber;}
}, (error) => console.log(error), () => {});
this.originalMaxSub = this.store.originalMax$.subscribe((originalMax) => {
if(originalMax !== null && originalMax !== undefined) {this.originalMax = originalMax;}
}, (error) => console.log(error), () => {});
this.selectionSub = this.store.selection$.subscribe((selection) => {
if(selection !== null && selection !== undefined) this.selectedAmount = selection.length;
}, (error) => console.log(error), () => {});
this.selectionOfInterestSub = this.store.selectionOfInterest$.subscribe((selectionOfInterest) => {
if(selectionOfInterest !== null && selectionOfInterest !== undefined) this.selectionOfInterest = selectionOfInterest;
}, (error) => console.log(error), () => {});
}
ngOnDestroy(){
this.maxSub.unsubscribe();
this.fromSub.unsubscribe();
this.toSub.unsubscribe();
this.pageNumberSub.unsubscribe();
this.originalMaxSub.unsubscribe();
this.selectionSub.unsubscribe();
this.selectionOfInterestSub.unsubscribe();
}
in regular old Observables you can just :
alive = true;
constructor(private store: StoreService) {}
ngAfterContentChecked(){
this.store.thing.subscribe().takeWhile(this.alive)...
}
ngOnDestroy(){
this.alive = false;
}
which is much simpler.
Isn't there a way to do the same with Behavior Subjects?
Another thing : am I missing a fundamental property of Behavior Subjects that they only subscribe once within an class no matter how many times the subscribe is called and that's why there's no such thing as takeWhile() on Behavior Subjects?
1 - Actually what you call it a simpler way does not unsubscribe at all it just stop reading what comes from the observable. So either use unsubscribe or complete.
2 - Since you are unsubscribing at the same time and you clearluy don't use the Subject for anything else, then it's fine to use the same Subject variable for all your subs and then you can unsubscribe with oneline of code and you don't need to initialize all these Subject instances.