react safari can't focus on input when clicked - html

I'm creating a search bar like so:
<form
id="search-bar-form"
onSubmit={e => {
e.preventDefault();
}}
>
<div id="search-bar-div">
<input
onChange={async e => {
console.log("I was changed");//debug
// Set the search term
setSearchTerm(e.target.value);
// Fetch results
await debouncedSearch(e.target.value);
}}
onKeyUp={onKeyUp}
type="text"
name="search"
id="search-bar"
aria-label="search"
value={searchTerm}
list="search-bar-autocomplete"
autoComplete="off"
placeholder={`🔍 ${t('searchbar.default-value')}`}
/>
<div>
<ul id="search-bar-autocomplete">
{searchResults &&
searchResults.length > 0 &&
searchResults.map((result, index) => (
<li
key={index}
style={
selectionIndex === index
? {
backgroundColor: '#e8e8e8',
}
: null
}
onClick={() => {
const selectedItem = searchResults[index];
setSearchTerm(selectedItem.name);
handleItemSelected(selectedItem);
}}
>
{result.name}
</li>
))}
</ul>
</div>
</div>
</form>
In Safari, and Safari only, I am not able to click in the input at all; I don't even see the cursor in there.
This is not the same as this question, because in this question the input can be selected and the cursor appears but they can't type. Even though it's not the same problem I did try the solution suggested in that question, which is to add the propertyy -webkit-user-select:textto the input, and it didn't work.
Question: why can't I focus in my input and how do I make it possible?

I propose user-select: text;. The webkit version is a polyfill.

Related

How do I calculate income and expense in an expense tracker JavaScript

I'm trying to add the value of a checked radio button in an object in another function.
However there is nothing being added and no error returned.
I'm building an expense tracker and adding those value (either income or expense) is important in my calculation.
Nb: when I try to console.log in the function where i capture the checked value, it works perfectly but when i try to add that value to the array object in another function nothing is added.
const TransactionType = document.getElementsByName('selector');
addbtn.addEventListener('click', function() {
if (expense.value == '' || amount.value == '' || date.value == '') {
alert('Please fill all the fields!!!');
return;
} else {
const userExpense = {
id: generateID(),
type: getTransactionType(), // here is the problem nothing is added
date: date.value,
expense: expense.value,
amount: amount.value
};
userInput.push(userExpense);
localStorage.setItem('data', JSON.stringify(userInput));
location.reload();
}
});
function getTransactionType() {
TransactionType.forEach(item => {
if (item.checked) {
return item.value;
}
});
}
<!-- radio buttons to choose the type of transaction -->
<div class="container">
<h3>Select the type of transaction:</h3>
<ul>
<li>
<input type="radio" id="type-income" name="selector" value="income">
<label for="type-income">Income</label>
</li>
<li>
<input type="radio" id="type-expense" name="selector" value="expense">
<label for="type-expense">Expense</label>
</li>
<!-- <button onclick=" getTransactionType()">see value</button> -->
</ul>
</div>
The code is incomplete. There is no addbtn and no handling of displaying the localStorage
Why do you reload?
TransactionType.forEach(item => {
if (item.checked) {
return item.value;
}
});
does nothing.
The return statement is not interesting in a forEach.
Here is a simpler method: I use delegation.
There is no need to test that anything is checked because you use radios. It needs more code if you were using a checkbox.
const getTransactionType = () => document.querySelectorAll('[name=selector]:checked')[0].value;
document.querySelector('.container').addEventListener('click', () => {
console.log(getTransactionType())
})
<!-- radio buttons to choose the type of transaction -->
<div class="container">
<h3>Select the type of transaction:</h3>
<ul>
<li>
<input type="radio" id="type-income" name="selector" value="income">
<label for="type-income">Income</label>
</li>
<li>
<input type="radio" id="type-expense" name="selector" value="expense">
<label for="type-expense">Expense</label>
</li>
</ul>
</div>

How to dynamically change the css style of a particular item inside a map function

I currently have two map functions to render a board for a chess game like this:
<div className='board'>
{rows.map((item) => (
<div key={item} className='row'>
{item.map((square) => (
# The square <div> => <div key={square[0]} className='square' onClick={() => {
board.select !== null &&
checkColour(board.select[1]) !== checkColour(square[1]) && dispatch(move(square))
}}>
{isNaN(square[1]) && <img src={square[1]} alt={square[1]}
onClick={() => { board.turns === checkColour(square[1]) && dispatch(select(square)) }}
className={board.select === square ? 'piece-selected' : 'piece'} />}
</div>
))}
</div>
))}
</div>
Now, I want to change the css style of certain squares <div> after I selected a pawn piece in order to forecast a shadow for showing the possible moves. I want to know is it possible to access the css style of that particular square <div> using the key of that <div>?
Feel free the drop a comment below if you have any insight or idea. Let me know if you want more info. Much appreciated.

Use modal on a v-for element?

I am getting a GET request from my api to disply all users , and i want to modify maybe the name of the email of each users with a modal. The problem is , imagine i have 3 users displayed , 3 modals will be displayed even if i press on only one modal button.
How can i do to fix it ?
there is my code :
<template>
<div class="container">
<div>
<h1>
<b> Users </b>
<input
type="text"
v-model="search"
class="search"
placeholder="Search User"
/>
</h1>
</div>
<div class="overlay-container">
<form>
<div class="form-group">
<div
v-for="user in filterUser"
v-bind:key="user"
class="form-control"
>
<p>
<b>{{ user.fname }} </b> {{ user.lname }}
</p>
<b-button v-b-modal.modal-1>Modifiy</b-button>
<b-modal id="modal-1" title="User Modification">
<p class="my-4">Please edit informations</p>
</b-modal>
</div>
</div>
</form>
</div>
</div>
</template>
<script>
import axios from "axios";
import VueAxios from "vue-axios";
export default {
name: "users",
data() {
return {
search: "",
users: [],
};
},
computed: {
filterUser() {
return this.users.filter((user) => {
return user.fname.match(this.search);
});
},
},
created() {
axios
.get(`http://localhost:4000/api/users`)
.then((Response) => (this.users = Response.data.data));
},
};
</script>
I want to each users open his own modal, not all modals when i press only one modal button.
I hope its clear !
First, pull out the modal inside of v-for, then create a method to get your user index, and add it to the Modify button. this is how you can get the data a user without sending another HTTP Request. and then you can show this.user data in your modal as you want.
<div
v-for="(user, index) in filterUser"
v-bind:key="user"
class="form-control"
>
<p>
<b>{{ user.fname }} </b> {{ user.lname }}
</p>
<b-button
v-b-modal.modal-1
#click="getUserInfo(index)"
>
Modifiy
</b-button>
</div>
data() {
return {
search: "",
users: [],
user: {}
};
},
methods: {
getUserInfo(index) {
this.user = this.users[index]
}
}

When I try to change colour depends on the count it show's the error TypeError: Cannot read property 'style' of null

In the below I would like to change the colour to black if the count is === 0
if(Count === 0){
document.getElementById('value').style.color = 'black';
}
return(
<div className='container_new'>
<h1>Counter</h1>
<span id='value'>{Count}</span>
<div>
<button className="btn decrease" onClick={handleDecrement} >decrease</button>
<button className="btn reset" style={{color: 'black'}} onClick={() => handleReset()}>reset</button>
<button className="btn increase" onClick={() => handleIncrement()}>increase</button>
</div>
</div>
)
You can achieve what you wanted this way.
return(
<div className='container_new'>
<h1>Counter</h1>
<span id='value' style={{ color: Count === 0 ? 'black' : 'white' }}>{Count}</span>
<div>
<button className="btn decrease" onClick={handleDecrement} >decrease</button>
<button className="btn reset" style={{color: 'black'}} onClick={() => handleReset()}>reset</button>
<button className="btn increase" onClick={() => handleIncrement()}>increase</button>
</div>
</div>
)
in react.js i would approach this differently because it render and change the DOM (html tree)
so maybe instead of using
**document.getElementById('value').style.color = 'black';**
make a class in CSS and change the className based on the Count
like this
css class
.black {
color : black;
}
.green {
color : green;
}
react.js code
<span id='value' className={Count === 0 ? "black" : "green" } >{Count}</span> // tell me if this line is understandable
replace this line with your line and see if is working !
it would help me understand better if you show us the the handle increment function handle reset and handle decrement :)
Create a local state for the count and track the update. Based on the count value in the state, update the template style.
const [count, setCount] = useState(0);
return(
<div className='container_new'>
<h1>Counter</h1>
<span id='value'>{count}</span>
<div>
<button className="btn decrease" onClick={handleDecrement} >decrease</button>
<button className="btn reset" style={{color: (count === 0 ? 'black': 'green')}}
onClick={() => setCount(0)}>reset</button>
<button className="btn increase" onClick={() => handleIncrement()}>increase</button>
</div>
</div>
I believe, your react state is state = { Count: 0 }, If yes, when react starts initial rendering, you're trying to get the element by id, at this time, there no element(not rendered) with <span id='value'>{Count}</span> which returns null. That's why you're getting this error Cannot read property 'style' of null.
But, you can simply use following solution
<span id="value" style={{ color: Count === 0 ? 'black' : 'green' }}>{Count}</span>

Post method doesn't work with html form in MVC

Why is that the $.post() method doesn't work ? I press the button but it doesn't post to EditClassLessonHour.
Here is the View Code:
<div class="jumbotron">
<form id="editClassLessonHour">
#Html.HiddenFor(model => model.ID)
<span> Classes : </span>
<select name="classes" id="classes">
#foreach (var item in ViewBag.classes as List<SelectListItem>)
{
<option value="#item.Value">#item.Text</option>
}
</select>
<br /><br />
<div class="input-group">
<span class="input-group-addon" name="lessons" id="lessons">Lessons : </span>
#Html.DropDownListFor(x => x.LessonName, (IEnumerable<SelectListItem>)ViewData["lesson"], new { #class = "form-control", placeholder = "Lesson", aria_describedby = "txtClassNumber" })
#Html.ValidationMessageFor(model => model.LessonName)
</div>
<br />
<div class="input-group">
<span class="input-group-addon" name="hours" id="hours">Hour : </span>
#Html.DropDownListFor(x => x.Hour, (IEnumerable<SelectListItem>)ViewData["hour"], new { #class = "form-control", placeholder = "Lesson", aria_describedby = "txtClassNumber" })
#Html.ValidationMessageFor(model => model.Hour)
</div>
<br />
<input type="button" value="Kaydet" id="kaydet" class="btn btn-success" onclick="post(); " />
</form>
<br />
</div>
<script>
$.post('/ClassLessonHour/EditClassLessonHour',{
classId: $('#classes').val(),
lessonId: $('#lessons').val(),
hourId: $('#hours').val()
}, function (result) {
$('#message').html(result.message);
});
</script>
Here is Controller Code
[HttpPost]
public ActionResult EditClassLessonHour(int classId, int lessonId, int hourId)
{
}
What can I do? I want that when I press the button, the form should be posted to the Controller.
onclick="post();"
You don't have a function called post. You don't have any function at all. You're just executing an AJAX POST request as soon as the page loads.
Remove that onclick attribute entirely and bind your AJAX call to the button's click event. Something like this:
$(function () {
$('#kaydet').on('click', function () {
$.post('/ClassLessonHour/EditClassLessonHour',{
classId: $('#classes').val(),
lessonId: $('#lessons').val(),
hourId: $('#hours').val()
}, function (result) {
$('#message').html(result.message);
});
});
});
Though it seems likely that there are more problems here. For example, this:
$('#lessons').val()
The id="lessons" element is a <span>, which doesn't have a "value". You want to target the <select> being generated by #Html.DropDownListFor, not the <span> that's near it. Examine your HTML in the browser to see what is being generated by that server-side code. It may have an id or name that you can use in your jQuery selector. (This same problem applies to your #hours element as well.)