OTP in react-native - react-native

I have 4 inputs on my login screen once the user fills in the first input the focus should be automatically moved to the next input but then I get an error while executing my script
Well, with react-native I try to activate the focus on my next input once the previous one is validated but I stall badly.
Here is my reference table
const inputRef = [
useRef(null),
useRef(null),
useRef(null),
useRef(null),
useRef(null),
]
my function to activate the focus on the next input
_next_input = (index) =>{
console.log(inputRef[index+1].current.focus)
}
my implementation
inputRef.map((reference_input , idx)=>(
<OtpCard
key={idx}
ref={ reference_input }
onChange = { (string)=> {
if(string != '')
_next_input(idx)
else
console.log('value is empty')
}}
/>
))

Related

How to make pattern in TextInput used for credit card in react native?

I want to make pattern text input for months and years. So, I made some logic but it's not working.
Below is the code:
const [monthYear, setMonthYear] = useState(null)
function _handlingMonthYear(number) {
setMonthYear(number.replace(/\s?/g, '').replace(/(\d{2})/g, '$1 ').trim());
}
<TextInput
onChangeText={(text) => _handlingMonthYear(text)}
placeholder='MM/YY'
value={monthYear}
/>
I want to make that if the user type 1234 then it should appear as 12/34 in TextInput.
you can use this regular expression
const monthYear=/(0[1-9]|1[0-2])\/(\d{4}[^0-9])/
var testDate="01/2022"
console.log("(monthYear.test(testDate))","it will log true")
var testDate="13/2022"
console.log("(monthYear.test(testDate))","it will log false")
I found this solution for the format look like as 'MM/YY'.
Below is the full code of my solution. It's working.
function _handlingMonthYear(number) {
setMonthYear(number
.replace(
/^([1-9]\/|[2-9])$/g, '0$1/'
).replace(
/^(0[1-9]|1[0-2])$/g, '$1/'
).replace(
/^([0-1])([3-9])$/g, '0$1/$2'
).replace(
/^(0?[1-9]|1[0-2])([0-9]{2})$/g, '$1/$2'
).replace(
/^([0]+)\/|[0]+$/g, '0'
).replace(
/[^\d\/]|^[\/]*$/g, ''
).replace(
/\/\//g, '/'
)
);
}

D3 linkHorizontal() update on mouse position

I’m trying to implement a drag and drop functionality with a connection line. The connection line has a starting point ([x, y]), which is gathered when the mouse is clicked and a target point ([x, y]) which follows the mouse position and is continuously updated while dragging the element.
The project uses Vue.JS with VUEX store and for the connection line D3.js (linkHorizontal method https://bl.ocks.org/shivasj/b3fb218a556bc15e36ae3152d1c7ec25).
In the main component I have a div where the SVG is inserted:
<div id="svg_lines"></div>
In the main.js File I watch the current mouse position (targetPos), get the start position from the VUEX store (sourcePos) and pass it on to connectTheDots(sourcePos, targetPos).
new Vue({
router,
store,
render: (h) => h(App),
async created() {
window.document.addEventListener('dragover', (e) => {
e = e || window.event;
var dragX = e.pageX, dragY = e.pageY;
store.commit('setConnMousePos', {"x": dragX, "y": dragY});
let sourcePos = this.$store.getters.getConnStartPos;
let targetPos = this.$store.getters.getConnMousePos;
// draw the SVG line
connectTheDots(sourcePos, targetPos);
}, false)
},
}).$mount('#app');
The connectTheDots() function receives sourcePos and targetPos as arguments and should update the target position of D3 linkHorizontal. Here is what I have:
function connectTheDots(sourcePos, targetPos) {
const offset = 2;
const shapeCoords = [{
source: [sourcePos.y + offset, sourcePos.x + offset],
target: [targetPos.y + offset, targetPos.x + offset],
}];
let svg = d3.select('#svg_lines')
.append('svg')
.attr('class', 'test_svgs');
let link = d3.linkHorizontal()
.source((d) => [d.source[1], d.source[0]])
.target((d) => [d.target[1], d.target[0]]);
function render() {
let path = svg.selectAll('path').data(shapeCoords)
path.attr('d', function (d) {
return link(d) + 'Z'
})
path.enter().append('svg:path').attr('d', function (d) {
return link(d) + 'Z'
})
path.exit().remove()
}
render();
}
I stole/modified the code from this post How to update an svg path with d3.js, but can’t get it to work properly.
Instead of updating the path, the function just keeps adding SVGs. See attached images:
Web app: Multiple SVGs are drawn
Console: Multiple SVGs are added to element
What am I missing here?
#BKalra helped me solve this.
This line keeps appending new SVGs:
let svg = d3.select('#svg_lines') .append('svg') .attr('class', 'test_svgs');
So I removed it from the connectTheDots() function.
Here is my solution:
In the main component I added an SVG with a path:
<div id="svg_line_wrapper">
<svg class="svg_line_style">
<path
d="M574,520C574,520,574,520,574,520Z"
></path>
</svg>
</div>
In the connectTheDots() function I don't need to append anymore, I just grap the SVG and update its path:
function connectTheDots(sourcePos, targetPos) {
const offset = 2;
const data = [{
source: [sourcePos.y + offset, sourcePos.x + offset],
target: [targetPos.y + offset, targetPos.x + offset],
}];
let link = d3.linkHorizontal()
.source((d) => [d.source[1], d.source[0]])
.target((d) => [d.target[1], d.target[0]]);
d3.select('#svg_line_wrapper')
.selectAll('path')
.data(data)
.join('path')
.attr('d', link)
.classed('link', true)
}

Refreshing Vuetify V-Calendar with new events hide the events in the "Month" view

Currently developing an appointment-making application using a C# API in Vue.js with Vuetify, I encounter a behaviour with the component V-Calendar I can't comprehend. When originally feeding events to the calendar (appointments retrieved from a database by contacting the API), those events are correctly displayed as followed :
Original calendar loading
The query originally ignores cancelled appointments. However, I give the option to include them with a checkbox in the calendar header. Checking the box automatically refreshes the list of events through a watcher. When doing so, the calendar has a strange behaviour and does no longer display the events. This only occurs in the "Month" view, the "Day" and "Week" ones correctly display the data.
Result of refreshing the calendar
Here is the definition of my calendar (programming in french, translated in english the variables/methods for your easier understanding)
<v-calendar ref="calendar"
v-model="focus"
:event-color="getEventColor"
:events="events"
:first-interval="13"
:interval-count="22"
:interval-format="intervalFormat"
:interval-minutes="30"
:type="type"
:weekdays="weekDays"
color="primary"
event-more-text="Show more"
event-overlap-mode="column"
locale="fr"
#change="updateRange"
#click:event="showEvent"
#click:more="viewDay"
#click:date="viewDay">
<template #event="event">
<div v-if="event.eventParsed.input.idEtat === etats.annule"><s><i>{{
event.eventParsed.input.name
}}</i></s></div>
<div>{{ event.eventParsed.input.name }}</div>
</template>
</v-calendar>
The definition of the updateRange method (called once when the page is loaded in the created() hook)
async updateRange({start, end}) {
this.currentDateDebut = start.date;
this.currentDateFin = end.date;
await this.refreshCalendarData();
}
The definition of the refreshCalendar method
async refreshCalendarData() {
this.loading = true;
const events = []
//Récupération des rendez-vous
await this.getRendezVous(this.currentDateDebut, this.currentDateFin);
this.rendezVous = await this.$store.getters["rendezVous/getRendezVousData"];
for (let i = 0; i < this.rendezVous.length; i++) {
const calculImcPossible = (this.rendezVous[i].taille != null && this.rendezVous[i].taille > 0) &&
(this.rendezVous[i].poids != null && this.rendezVous[i].poids > 0);
const calculImc = calculImcPossible
? (Math.round(this.rendezVous[i].poids / ((this.rendezVous[i].taille / 100) * (this.rendezVous[i].taille / 100)) * 100) / 100).toFixed(2)
: null;
const libelleImc = this.getLibelleImc(calculImc);
events.push({
id: this.rendezVous[i].id,
idInstitution: this.rendezVous[i].idInstitution,
name: this.heureCourte(this.rendezVous[i].date) + " | Appointment",
start: new Date(this.rendezVous[i].date),
end: new Date(new Date(this.rendezVous[i].date).getTime() + 15 * 60000),
color: this.rendezVous[i].institution.color,
timed: true,
taille: this.rendezVous[i].taille != null && this.rendezVous[i].taille > 0
? this.rendezVous[i].taille + "cm"
: "indéfinie",
poids: this.rendezVous[i].poids != null && this.rendezVous[i].poids > 0
? this.rendezVous[i].poids + "kg"
: "indéfini",
sexe: this.rendezVous[i].patient.sexe,
imc: calculImc != null ? (calculImc + " (" + libelleImc + ")") : "non-déterminé",
nom: this.rendezVous[i].patient.nom + " " + this.rendezVous[i].patient.prenom,
telephone: this.rendezVous[i].patient.telephone != null ? this.rendezVous[i].patient.telephone : "-",
email: this.rendezVous[i].patient.email != null ? this.rendezVous[i].patient.email : "-",
commentaire: this.rendezVous[i].commentaire,
regime: this.rendezVous[i].regime,
hospitalisation: this.rendezVous[i].hospitalisation,
contagieux: this.rendezVous[i].contagieux,
incontinent: this.rendezVous[i].incontinent,
naissance: this.dateCourte(this.rendezVous[i].patient.naissance),
diabete: this.rendezVous[i].diabete.type,
examen: this.rendezVous[i].examen.nom,
idEtat: this.rendezVous[i].idEtat,
idPatient: this.rendezVous[i].idPatient,
typeEvent: "rendez-vous",
editable: this.rendezVous[i].editable
});
}
}
And finally, the definition of the watcher showCancalledAppointments
async showCancelledAppointments() {
await this.refreshCalendarData();
}
Do you have any idea why this behaviour is displayed by the calendar ? Thank you for your time and help.
Updating the solution with the command 'npm update' fixed the problem. The latest version of Vuetify seems to solve the issue

Vue.js Nuxt - cannot access Array (value evaluated upon first expanding error)

I have the following function which gives me an array called URLs
const storageRef = this.$fire.storage.ref().child(fileName)
try {
const snapshot = storageRef.put(element).then((snapshot) => {
snapshot.ref.getDownloadURL().then((url) => {
urls.push(url)
})
})
console.log('File uploaded.')
} catch (e) {
console.log(e.message)
}
});
console.log(urls)
console.log("about to run enter time with imageurls length " + urls.length)
When I run console.log(URLs) initially I do see the array like the following
[]
0: "testvalue"
length: 1
__proto__: Array(0)
However, there is a small information icon stating
This value was evaluated upon first expanding. The value may have changed since.
Because of this, when I try to get the length of URLs, I get zero, meaning the value is being updated.
Does anyone know what's happening? I am using Vue.JS/Nuxt.

React Native TextInput: How to know index of character typed by user

In React Native TextInput, how can I know the index of typed character by user?
example: This is joe
If the user moves cursor after "is" word and types "This is not joe".
I want to know index of user typed characters " " then "n" and then "o" and then "t".
I do get what user typed in onKeyPress
const keyPressHandler = (e) => {
console.log(e.nativeEvent.key + "Pressed");
console.log(e.nativeEvent);
setKeyPressed(e.nativeEvent.key);
}
This is my TextInput field
<TextInput
{...props}
style = {styles.textField}
multiline = {true}
textAlignVertical = 'top'
placeholder = 'Enter your text'
onChangeText={onChangeTextHandler}
onChange = {onChangeHandler}
onBlur={lostFocusHandler}
onKeyPress = {keyPressHandler}
value = {postText}
/>
I am writing a component where when a user types " #" i am showing a list of users to mention them in post, so I need to know the index of typed character and then need to know if there is space before typed character and then only to show users list.
I would use a piece of state to hold the text input and then use an Effect to check the string each time the value changes for the # symbol.
Something like:
import {useEffect, useState} from 'react-native';
const MyTextInput = () => {
const [value, setValue] = useState(null);
useEffect(() => {
if(value.indexOf('#') !== -1){
const index = value.indexOf('#');
** Do Something **
}
}, [value]);
return (
<TextInput
{...props}
style = {styles.textField}
multiline = {true}
textAlignVertical = 'top'
placeholder = 'Enter your text'
onChangeText={setValue}
onChange = {onChangeHandler}
onBlur={lostFocusHandler}
value={value}
/>
)
}
The reason I suggest the above method is that the onKeyPress function doesn't work for android hardware keyboards, whereas, the above method will work for everything.
The method above will also give you the index of # so that you can get the substring after it.
NOTE: The indexOf method will only look for the first # in the string. A Regex might help for scenarios where the user can enter multiple #.
onSelectionChange gives the cursor position. Start and end position is same as you move cursor around. If select something then it will differ/
const selectionChangeHandler = (e) => {
console.log("Selection change handler Start = " + e.nativeEvent.selection.start + "End =" + e.nativeEvent.selection.end);
setCursorPosition(e.nativeEvent.selection);
};
<TextInput
{...props}
style = {styles.textField}
multiline = {true}
textAlignVertical = 'top'
placeholder = 'Enter your text'
onChangeText={onChangeTextHandler}
onChange = {onChangeHandler}
onBlur={lostFocusHandler}
onKeyPress = {keyPressHandler}
onSelectionChange = {selectionChangeHandler}
selectTextOnFocus = {false}
value = {postText}
ref={postTextInputField}
/>