Javascript suddenly can not read value - javascript

I'm in the process of writing a client side app that given the ingredients will give you cocktail recipe. When inputted, you click on a button will search the ingredients. If "all" is entered you will be redirected to page with all the recipes.
I had just started this so note the all feature is the only part I've done.
It was working fine. For practice I had it when you entered "all" it would redirect to facebook's url. Out of nowhere(with no new changes) it started throwing me an error, it wasn't reading the input, it was reading it as null.
The relevant HTML:
<input type="text" id="alcohol">
<h4 class="btn" type="submit" onclick="whole()"> Search</h4>
The JS:
var input = document.getElementById('alcohol').value;
function whole() {
if (input == "all") {
window.location = "http://www.facebook.com";
};
};
What's happening here? Why did it stop working?

We need to see a greater context to know for sure, but it appears that you are probably getting the alcohol value too soon before it contains the latest value.
You can change to this to make the whole() function work with the current value of the alcohol field:
function whole(){
var input = document.getElementById('alcohol').value;
if (input =="all"){
window.location="http://www.facebook.com";
};
};
Remember that this:
var input = document.getElementById('alcohol').value;
gets the current value at the time that line of code is run. Any future changes to that field will not affect the input variable. That variable contains the value from a specific point in time only. The easiest way to avoid issues like this is to just get the value right when you need it, not some time earlier.

Related

Check if a Radio Button Selection has changed

I am trying to learn basics of Angular and stuck with a particular doubt. I have a set of dynamically generated radio button and one of them will be selected by default.
I want to check and detect the change of selection of radio button. This might not be particularly related to angular or maybe logic based question. Below is what I have attempted.
$scope.selectedReason= function(radio1)
{
$scope.radio7=radio1.id; // now radio7 has the value of radio7 e.g "12345"
$scope.bankAccount=radio1;
}
// another function where I am checking if the selected value is not same as new value
$scope.selectedAmount= function(radioSelect)
{
console.log($scope.radio7); // old value 12345
$scope.preselectedAccount = $scope.radio7; // hoping to store old value
$scope.selectedValue = $scope.preselectedAccount;
if ($scope.selectedValue == $scope.radio7){
console.log("Success");
}
}
Baiscally I am trying to store old value to a variable and check but its obvious that every time a new value comes the variable takes that value so there is not point in doing this. Any way I could pertain my old value check with new values.
Edit:
Input
<input type="radio" id="child_{{$index}}" name="radio2" ng-model="selectedBankAccount" ng-value="bankAccount" ng-click="selectedReason(bankAccount)">
You can use the change event for it
// you can pass anything in the function
<input type="radio" (change)="handleChange(child_{{$index}})" />
and in your TS file implement the handleChange function and do what you want.
handleChange(id) {
console.log(id);
}

How do I detect whether or not an input with type=time has any values entered

I have a javascript script that's supposed to detect whenever an html form input with type="time" has any value entered.
However, whenever I enter a partial value (for instance, type one number, instead of a full time with AM/PM), it doesn't detect the input as having a value.
In the below example, timeSelector is the input with type="time".
if (timeSelector.value == "") {
timeSelector.classList.add("empty");
} else {
timeSelector.classList.remove("empty");
}
Is there any way to detect this type of thing?
To clarify, since apparently I didn't ask my question clearly enough, I need to detect when a time input has something entered, even if that something is an invalid or incomplete input.
Well the problem with html5 inputs is they do not give the text in the input if it is not valid. So you can use checkValidity when the user removes focus from the element.
var checkInput = function() {
var value = this.value
var isValid = this.checkValidity()
if (!this.value.length && isValid) {
console.log('empty');
} else if (!this.value.length && !isValid) {
console.log('invalid time entered')
} else {
console.log('valid time entered')
}
}
var input = document.querySelector("input")
input.addEventListener("input", checkInput)
input.addEventListener("blur", checkInput)
<input type="time" />
Per the specification on Input Elements with type time ( HTML Spec ) :
The value attribute, if specified and not empty, must have a value that is a valid time string.
If the value of the element is not a valid time string, then set it to the empty string instead.
This means that input and change events don't occur until the entire time field has been filled out. Why? Because nothing really has changed.
You may think that you can circumvent this by using keydown or keyup events, but this is simply not the case.
The value is not changed and is therefore inaccessible until a full string that is capable of being parsed as a time is inside the time input box.
By filling in the below example you can see how the events fire. Notice the lack of value until everything is filled in.
let i = document.querySelector("input"),
on = type => i.addEventListener(type, function() { console.log(`${type}, value: ${i.value}`); });
on("keydown");
on("keyup");
on("change");
on("input");
<input type="time">
The only way to possibly get around the lack of a changing value is to set a default value as below:
let i = document.querySelector("input"),
on = type => i.addEventListener(type, function() { console.log(`${type}, value: ${i.value}`); });
on("change");
<input type="time" value="00:00">
However, with a default value there is a risk that the user will submit a time that isn't something that you'd likely want.
You could write some validation code to take care of this depending on the complexity of your functionality this may be possible.
Overall if this is something you need and the functionality is a bit more complicated than you think you can handle validating yourself, it would be best to either create your own time input interface from other input types, or to use a library or UI kit from a source that has already done the legwork.

Adding the numbers of textbox giving wrong result

I am creating a web app in which I have a number in my $scope variable
$scope.total=20;
and I have one textbox
<input type="text" ng-model="amount1" ng-change="amountchange(amount1)" />
and when a user enters 500 in the textbox it should be 700 but instead the answer is coming 755 and when I delete 500 from my textbox it became null.
I just want to add or remove from my textbox what I am doing wrong here
Here is a fiddle created by me for better understanding
this problem is in this line:
$scope.total = parseInt($scope.amount1) + parseInt($scope.total);
you aggregate the value when you enter more input instead of just sowing the result.
what you can do is simple, add this method:
$scope.getTotal=function(){
return parseInt($scope.amount1) + parseInt($scope.total);
}
and replace {{total}} with this: {{getTotal()}}
It happens because of ng-change, each time the value is getting added
On entering 500,
Step1 5 + 200
Step2 50 + 205
Step3 500 + 255
and so it becomes 755. Use ng-blur instead of ng-change
<body data-ng-controller="myController">
<input type="text" ng-model="amount1" ng-blur="amountchange()" />
{{total}}
</body>
DEMO
What happens in your app is actually expected, because you add the current number on each input change.
Changing to ng-blur or setting a timeout before updating the value, using the built-in ng-model-options, which can now be done as of Angular 1.6 (released just yesterday) could be good options.
<input type="text" ng-model="amount1" ng-change="amountchange()" ng-model-options="{'debounce':{'default':300}}" />
or:
<input type="text" ng-model="amount1" ng-blur="amountchange()" />
However, I do not recommend either of them, and here's why:
By not letting the user decide when the data they entered is submitted (e.g.: pressing enter or a submit button) you make it user-unfriendly as well as introduce unwanted behaviour, such as when the user clicks off and on the in the second example, the number will have been added again and again...
Consider using a form and ng-submit instead as it's cleaner, more semantic and also conveys a friendlier way for your users to submit data.
Also here's the solution to your other issue:
$scope.amountchange = function () {
var amount = ($scope.amount1 != '') ? $scope.amount1 : 0;
console.log(amount)
if (amount != NaN) {
$scope.total = parseInt(amount) + parseInt($scope.total);
}
else {
alert("Please enter a number.");
$scope.amount1 = $scope.total;
}
}
To explain: first off you did not make use of any arguments, so you do not need to pass the amount1 model's value into the function in your directive. But that wasn't the problem. The reason why it set it to null is that the empty field doesn't parse to a 0, therefore you have to set it yourself. I saved the value into the variable amount on the function and assigned either the value of $scope.amount or 0 if it happens to be empty.

Meteor: How to set a number based on the number of checked boxes within a section

I currently have a multi-section form, with a number of checkboxes. What Im trying to do, is show the number of checked boxes, next to the total. I have total showing up just fine, but I cant for the life of me figure out a way to loop over the inputs, successfully find the :checked, and print that number out.
I think the main thing causing me issues, is that it needs to update every time a new box is checked. Heres some of the code.
Event Handler
'click input[type=checkbox]': function(){
Session.set('selectedPlayerCount', n);
Session.get('selectedPlayerCount');
}
The goal here is to set the number of selected players, and pass it to the template/helper.
Helper
countSelected: function(){
n = 0;
n++;
var selectedPlayerCount = Session.get('selectedPlayer');
return selectedPlayerCount;
}
Within the helper I'm attempting to iterate every time the event is triggered, and as a result increase the value by one. I'm aware that resetting n back to 0 is going to cause some issues, and I know that needs to be changed one the rest is figured out. I just cant figure out where the variable needs to be set in order to provide a default value.
Template
<header>
<p>{{ countSelected }}</p>
</header>
All I'm trying to do here for now is to print out the value rendered by the helper. I don't believe this is causing any issues.
TL;DR - How to count number of checked inputs within a section of a form, and for each one, increment a value, and then return it every time its changed.
I'm new to this but maybe this will serve: define your account to zero in a session variable, each time you select a checkbox you increase the value of your session variable
Session.set("countPlayersChecked", 0);
Template.proof.helpers({
countSelected: function () {
return Session.get("countPlayersChecked");
}
});
Template.proof.events({
'click input[type=checkbox]': function (event) {
if($(event.target).is(':checked'))
Session.set("countPlayersChecked", Session.get("countPlayersChecked")+1);
else
Session.set("countPlayersChecked", Session.get("countPlayersChecked")-1);
}
});
Hope it serves.

How can I ensure that changes to a form DOM are complete before POSTing?

Currently I have a race condition existing in my JavaScript code. What I am trying to do with this code is convert all check boxes which are a part of the 'checkbox' class and are not checked into text boxes with a value of zero. Currently when you post a check box that is not checked it does not appear in the $_POST data. However I need to know all the values whether true or false for these particular set of check boxes.
The code I have is here:
Code:
function checkboxConvert() {
var chkBxs = $$('.checkbox');
for (var i = 0; i < chkBxs.length; i++) {
if (chkBxs[i].checked == false) {
chkBxs[i].type = 'textbox';
chkBxs[i].value = '0';
}
}
setTimeout("document.productForm.submit();",1000);
}
Now the problem that I have been getting is that when I try to submit this form the values of the recently changed text boxes does not appear in the $_POST data. Therefore, as you can see above I have postponed the page submit for 1 sec and then I have all the data available to me. However as time goes on and my data set gets larger, 1 sec may no longer be enough. This I think is a race condition and I need to figure some way of running the code only after all the check boxes have been converted and they have their new values. I would have thought that this would be unnecessary from the start, but for some reason it's trying to run both pieces simultaneously and I can't submit until I have the proper values in place.
Any help is much appreciated!
This is definitely not the way to do web. I strongly advise you abandon your checkboxConvert function, and solve this issue on the server side
JavaScript always runs single-threaded in the browser so I don't think it can be a race condition.
I'd generally agree with others that you shouldn't do this, but your problem may be that you're changing the element to a type of "textbox" instead of "text". If you declare an input of type "textbox" in HTML markup, it will usually render as a text field anyway because that's the default. However, changing an already valid "checkbox" type input to the invalid "textbox" may not work predictably.
Try changing it to this:
function checkboxConvert() {
var chkBxs = $$('.checkbox');
for (var i = 0; i < chkBxs.length; i++) {
if (chkBxs[i].checked == false) {
chkBxs[i].type = 'text';
chkBxs[i].value = '0';
}
}
// Because JS in the browser is single-threaded, this
// cannot execute before the preceding loop completes anyway.
document.productForm.submit();
}
There's got to be a better way to do this. Try something like:
Know about all your possible values on the server side. It looks like you're using PHP; keep a simple array with the names of your checkboxes.
When you take your $_POST data, remove the names of checkboxes you've received values for from your array.
The remaining are all false.

Categories

Resources