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
Related
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
if (!date.value && !startTime.value && !endTime.value) {
[startTime, endTime, date].forEach(item => {
{
item.addEventListener("change", function () {
console.log(`${date.value}` + "T" + `${startTime.value}` + ":00" + "Z" + ","
+ `${date.value}` + "T" + `${endTime.value}` + ":00" + "Z"
);
}
)
}
})
}
In the Code above I only want the console.log to execute when all conditions
if (!date.value && !startTime.value && !endTime.value)are fullfilled. Now it always console.logs a value if only one condition is met.
When I check for these values:
console.log(startTime.value);
console.log(endTime.value);
console.log(date.value);
The console just shows me an empty line. So their default values should be "", right?
Does someone know why the function gets executed when only one value is changed?
You keep adding listeners when you don't need to. Initially add the listeners to the inputs, and then have a function to handle what happens.
// Grab the inputs
const inputs = document.querySelectorAll('input');
// Add a listener to each - note that depending on the number of
// inputs you have you might want to switch to event delegation
// https://dmitripavlutin.com/javascript-event-delegation/
[...inputs].forEach(input => {
input.addEventListener('change', handleChange, false);
});
function handleChange(e) {
// Now just check to see if any of the inputs are empty
const allAreEmpty = [...inputs].every(input => {
return input.value === '';
});
// And return an answer only when none of the
// inputs are empty
if (allAreEmpty) console.log(1);
}
<input id="date" />
<input id="startTime" />
<input id="endTime" />
Additional documentation
Array.prototype.every
Thank you for your answers!
I found a solution looking like this:
//checking for change of all values. Then console.log values on change and executing request if busy.
[...inputs].forEach(input => {
input.addEventListener('change', function () {
if (date.value !== "" && startTime.value !== "" && endTime.value !== ""
) {
console.log(`"${date.value}T${startTime.value}:00Z",
"${date.value}T${endTime.value}:00Z"`);
freeRequest.execute(function (resp) {
console.log(resp);
})
} else {
console.log("change date pls")
}
}
)
}
)
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
I have a variable with the number of select items, this number depends on some API, and I want to store the selection of each question into localstorage so each time the page reloads the selection stays remained, I don't know how to do it.
{ Object.entries(this.state.liste).map( ([ke,values]) => {
let question=ke
return (
<div name = "question" >
<h6 className="left">{ke}</h6>
< select className="right" key={values} name = "answer to each question" onChange={(event) =>
this.handleChangeaa(question,event)} >
<option value={this.state.selected} selected disabled hidden onChange={(value)=>
console.log(value)}> Not answered </option>
{Object.values(values).map(key=>{
return (<option key={key.id} id={key}>{key}</option>) })}
</select>
</div>
) })}
In localStorage, you can only set a value as a string. You simply have to insert in the localStorage some pairs of key/values for each questions that have a selected option. In this case, the key will be the id of your question and the value the value of your selected option.
In your handleChangeaa callBack, you will have something like this :
handleChangeaa(question, event) {
// Check before if the localStorage is available
localStorage.setItem(question.id, event.target.value);
}
Then when your form component will be instantiated, you will simply have to retrieve this information from your localeStorage with the localStorage.getItem function :
componentDidMount() {
// Check if localStorage is available
const stateListCpy = {...this.state.liste}
["question1", "question2"].forEach((questionId) => {
const questionValue = localStorage.getItem(questionId);
if (questionValue) {
const questionIndex = stateListCpy.findIndex((questionBlock) => questionBlock.ke === questionId )
if (questionIndex !== -1) {
stateListCpy[questionIndex].values = questionValue;
}
}
})
this.setState({
liste = stateListCpy;
})
}
And with that you will have your selects initialized with the right values from your localStorage.
Good luck !
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