array removes the last element instead of the removed one react useState - javascript

I am trying to get this
https://www.youtube.com/watch?v=QyoSW2cP-RE
My code is here
https://codesandbox.io/s/ecstatic-shannon-gz3c2?fontsize=14&hidenavigation=1&theme=dark
I am trying to delete element when the input field is empty, and it is working in the array (the 2 buttons in the bottom are for logging the array and it's working fine) but in the ordered list something is going wrong, it is deleting the last element and letting the removed one empty not deleting it, what's the problem I don't understand ://
<ol>
{prosArr.map((e, key) => {
if (e !== '') {
console.log(e);
return (
<li key={key}>
<input
type="text"
onBlur={(el) => {
if (el.target.value === '') {
prosArr[prosArr.indexOf(e)] = '';
setProsArr(prosArr.filter((e) => e !== ''));
}
}}
defaultValue={e}
/>
</li>
);
} else {
return '';
}
})}
<li>
<input
onBlur={(e) => {
e.target.value !== '' && setProsArr([...prosArr, e.target.value]);
e.target.value = '';
}}
type="text"
/>
</li>
</ol>;
EDIT: I edited and copied the functionality code here, but there is the full working code on the sandbox link

Related

Angular ngbTypeahead filter of list

I've got a ngbTypeahead which when typing in the field should be able to get a list of strings.
<ng-template #rt let-r="result" let-t="term">
<a>
<span class="ml-1">
<ngb-highlight [result]="r" [term]="t"></ngb-highlight>
</span>
</a>
</ng-template>
<div class="form-group row mb-1">
<label for="libelle" class="col-md-3 text-right pr-0">Employeur</label>
<div class="col-md-3">
<input class="form-control ml-1" id="libelle" name="libelle"
[(ngModel)]="libelle"
placeholder="Employeur"
[ngbTypeahead]="search"
(selectItem)="selectItemLibelle($event)"
[inputFormatter]="formatMatches" [resultTemplate]="rt"
(focus)="focus$.next($event.target.value)"
>
</div>
</div>
the typscript code :
search = (text$: Observable<string>) => {
const debouncedText$ = text$.pipe(debounceTime(200), distinctUntilChanged() );
const inputFocus$ = this.focus$;
return merge(debouncedText$, inputFocus$).pipe(
mergeMap((term) => {
return this.getEmp(term).pipe(map((emp: any) => {
return ((!term || false || term === '') ? emp
: emp.filter(v => v.toLowerCase().indexOf(term.toLowerCase()) > -1));
}));
})
);
}
selectItemLibelle($event) {
this.libelle = $event.item;
$event.preventDefault();
}
formatMatches = (value: any) => value || '';
the method getEmp, get the list of strings :
getEmp(term): Observable<any[]> {
this.fe2ModeleService.getEmployeurs(term).subscribe((employeurs) => {this.listEmp = employeurs;});
return of(this.listEmp);}
everything works fine, when I search with a character or a phrase I get the list , my issue is I want when I click on the input (when the input is empty) I want to have the complete list.
the problem is when I come the first time in the page or I refresh the page, and I click on the input nothing is displayed, but when I click elsewhere (on another input or on anywhere on the page) and I come back and click on the input, and there I have the list displayed.
how can I have this behavior from the first time I come to the page
get the complete list when I click on the input
I used combineLatest instead of mergeMap:
search: OperatorFunction<string, readonly PostCategory[]> = (text$: Observable<string>) => {
const debouncedText$ = text$.pipe(debounceTime(200), distinctUntilChanged());
const clicksWithClosedPopup$ = this.click$.pipe(filter(() => !this.instance.isPopupOpen()));
const operations$ = merge(debouncedText$, clicksWithClosedPopup$, this.focus$, this.clear$);
return combineLatest([
operations$,
this.categories$
]).pipe(
map(([text, categories]) =>
text === '' ? categories : categories.filter(c => new RegExp(`^${text}`, 'i').test(c.name)))
);
}
You can find the working code here: https://github.com/DeborahK/Angular-posts

react hooks: input onChange first character can not be deleted

I got some inputs to create/update a formular,
1) if value={question}, everything works except that I can not delete the last character (= first character of the input)
2) if I dont mention value, it's all good except when I want to change questions orders with Chevron icon button, database is well changed but input value is still displayed at the last place.
<input
type="text"
value={question}
placeholder="blabla"
onChange={event => {
event.preventDefault();
const value = event.target.value;
setUpdatedQuestion(value);
}}
/>
I tried to add if (event.target.value == "" || event.target.value) to onChange but does not work either
OK I found something, but it is a McGyver tip, not very clean : adding one space before all new add question ahah. But then I can't see my placeholder anymore :/
FYI : question is coming from a questions.map, setUpdatedQuestion do update questions, newOrder also do update questions
//in QuestionsContent.js (questions is a questions tab)
const QuestionsContent = props => {
return (
<form onSubmit={onSubmit}>
{isLoading === false && questions.length > 0
? questions.map((question, i) => {
return (
<div key={i}>
<QuestionLine
{...question}
questions={questions}
setQuestions={setQuestions}
setNewOrder={setNewOrder}
/>
</div>
);
})
: null}
<button
onClick={event => {
event.preventDefault();
setAddQuestion({
question: null,
type: "texte"
});
}}
>
Add a question
</button>
</form>
);
};
//in QuestionLine.js:
const QuestionLine = ({
question,
setNewOrder,
setQuestions,
questions
}) => {
const [updatedQuestion, setUpdatedQuestion] = useState("");
// * UPDATE QUESTION *******************************
useEffect(() => {
if (updatedQuestion !== "") {
const tab = [];
for (let j = 0; j < questions.length; j++) {
if (j === i) {
const newObject = {
question: updatedQuestion,
type: type
};
console.log("adding updatedQuestion ===>", newObject);
tab.push(newObject);
} else {
tab.push(questions[j]);
}
}
setQuestions(tab);
setUpdatedQuestion("");
}
}, [updatedQuestion]);
return (
<div >
{/* QUESTION */}
<input
type="text"
value={question}
placeholder="blabla"
onChange={event => {
event.preventDefault();
const value = event.target.value;
setUpdatedQuestion(value);
}}
/>
</div>
);
};
thanks for your precious help
The problem probably comes from the condition in the useEffect : when you want to delete the last character of the string, the state of updatedQuestion is empty and therefore the condition is not executed

How to make a function that can be edited and saved

In this situation when I add a todo item to the list and try to edit the added todo, it will only add one new letter and typing the next letter it will only replace the latest letter all the time. For instance, the word is hello, no matter how many letters you type there will be only one letter added (for instance hellop, hellow, hellol, hellop). Check the console.log to understand the problem.
link to snippet
const addTodo: AddTodo = newTodo => {
newTodo.trim() !== "" && setTodos([...todos, { text: newTodo, complete: false, edit: false }]);
}
const getEditText: GetEditText = getEditedTodo => {
console.log('getEditText ' + getEditedTodo);
}
const saveEditedTodo: SaveEditedTodo = currentTodo => {
console.log('saveEditedTodo ' + JSON.stringify(currentTodo.text));
}
return (
<div>
<input type="input" onChange={(e) => getEditText(e.target.value)} value={todo.text} />
<span onClick={() => saveEditedTodo(todo)}>Save</span></div> :
<li>
)
You are not assigning the new value to variable todo.next
You need to update the variable to which value is binded for input field. So please try to create a fiddler for these kind of questions

Change color of all occurrences of a character javascript/reactjs

I am working with reactjs have a form with multiple input fields and some of them have labels with an asterisk to indicate that the field is mandatory. I want to change the color of all the asterisks(*) to red for better visibility to the user. How can I change the color of all occurrences of the asterisk in my form to red at once?
PS : I don't want to put the asterisk in a span or a div. Rather I would like to write code so that every asterisk in the form gets the color red with a single piece of global code.
You should wrap asterisks in span element and assign some class. So you can give color to that class element in your css file.
Like this
<span class="required">*</span>
And in CSS
.required
{
color:red;
}
It's rather unclear what exactly you're trying to accomplish without having any code to reference. But I'm assuming what you're actually trying to highlight the asterisks (*) belonging to labels for fields that are empty during form-submission.
Try something like this: https://codesandbox.io/s/holy-leftpad-hw1oe
class App extends React.Component {
state = {
name: "",
password: "",
errors: false
};
handleOnChange = event => {
this.setState({
[event.target.name]: event.target.value
});
};
handleOnSubmit = event => {
event.preventDefault();
const { name, password } = this.state;
if (name.length === 0 || password.length === 0) {
this.setState({
errors: true
});
} else {
this.setState({
errors: false
});
}
};
render() {
const { name, password, errors } = this.state;
return (
<form onSubmit={this.handleOnSubmit}>
<label>
Name{" "}
<span
className={errors && name.length === 0 ? "error-label" : "label"}
>
(*)
</span>
</label>
<input name="name" onChange={this.handleOnChange} />
<label>
Password
<span
className={
errors && password.length === 0 ? "error-label" : "label"
}
>
(*)
</span>
</label>
<input name="password" onChange={this.handleOnChange} />
<button type="submit">Submit</button>
</form>
);
}
}

unable to delete character from input

I am debugging a project built by someone else and there's this strange issue where one of the form boxes cannot delete the last character.
The code uses two JS files, one mostly with React and the other with jQuery (I heard it was a legacy project that got outsourced and someone else just put react on top of it).
Now, because the code is 8000 lines long, it's been relatively difficult for me to debug (especially when they name everything the same...).
I was wondering if anyone would have any pointers? I checked the state and I can see that the value of the form input is changing (if the word "hello" is there and I delete all the way to "h" and delete again, "h" still stays in the box, but "h" is gone from the "value" field and from the state).
I suspected that it was a jQuery issue, but I do not see anything modifying the form input field values.
Another thing I've noticed is that I cannot CTRL + Delete or Highlight all and Delete at all (it works for the other boxes).
Here's a snippet of the React code for the input.
render: function() {
if( this.state.theData.length ) {
return (
<div id="to-airport-wrapper" className="wrapper">
<label htmlFor="to-airport" className="clear-inline-block">
{LEXICON.to}
<span className="sr-only">{LEXICON.cityOrAirport}</span>
<span id="wcag-to-airport" className="sr-only">{LEXICON.wcagFromToAirportLabel}</span>
<ToAirportLabel hasError={this.state.error}/>
</label>
<div id={"TO_LAW_"+this.props.groupIndex} className="list-airport-wrapper">
<input type="text" id="to-airport" className="from-to-airport full-width" name="to-airport"
onFocus={this.onFocus} onChange={this.change} placeholder={LEXICON.cityOrAirport}
aria-required="true" aria-autocomplete="list" autoComplete="off"
data-airportcode={this.state.airportcode} value={this.state.value}/>
<ul data-type="to-airport" className="list-airport list-unstyled">
{
this.state.data.map(function(item, i) {
return <li key={i} className="list-airport-item" data-shortname={item.shortName} data-airportcode={item.airportCode} tabIndex="-1"><span>{item.name}</span></li>
})
}
</ul>
</div>
</div>
);
} else {
return (
<div id="to-airport-wrapper" className="wrapper">
<label htmlFor="to-airport" className="clear-inline-block">{LEXICON.to}</label>
<div className="list-airport-wrapper">
<input type="text" id="to-airport" className="from-to-airport full-width" name="to-airport" onChange={this.change} disabled="true" aria-autocomplete="list" data-airportcode="" placeholder={LEXICON.cityOrAirport} autoComplete="off" value="" />
</div>
</div>
);
}
}
Here's the Change function:
change: function(event) {
GLOBAL.ToAirportSetAirportCode('', '');
console.log("TO VALUE!", event.target.value)
if( event.target.value ) {
var jsObjects = this.state.theData;
var result = jsObjects.filter(function( obj ) {
var airportName = obj.name.replace('(','\\(').replace(')','\\)');
var eventTargetValue = event.target.value.replace('(','\\(').replace(')','\\)');
return airportName.toLowerCase().search( eventTargetValue.toLowerCase() ) !== -1;
});
if( result.length > 0 ) {
$("#TO_LAW_"+this.props.groupIndex+ " ul").show();
this.setState({
data: result,
value:event.target.value
});
} else {
this.setState({
value:event.target.value
});
$("#to-airport + ul").hide();
}
} else {
this.setState({
data: this.state.theData,
value: event.target.value
});
}
if( event.target.value == "" || result.length == 0 ) {
this.reset(event.target.value);
}
}
The console.log for the TO VALUE disappears prematurely when I try to delete the last character in the form input.

Categories

Resources