ng-model misbehaving with HTML reset method - javascript

Im trying to be as ellaborative as i can with my question....
Scenario:
I have three input fields in my html page Two of them are to accept user inputted values and the third one binds(adds) these two values.
Done so far:
I initially used <input value="{{value1+value2}}" id="value3"/> which took the values as string; solved this issue by substracting the string by 0. But, this calculated values wont go off even using the reset button.
Then someone here on SOF told me to use <input ng-model="(value1-0)+(value2-0)" id="value3"/> which works, but i noticed that even though the values disapper visually the model still holds some value.
(When, i enter some value into the first input field, the third calculated field add the value of the inputted field with the previous value of the second input field(value that the second field had previous to the reset)
NOTE:
Reset method resets the values of the first two user inputted fields, but not that of the third calcualtion field while using <input value="{{value1+value2}}" id="value3"/> OR <input ng-bind="value1+value2" id="value3"/>
While, when using <input ng-model="(value1-0)+(value2-0)" id="value3"/> the calculated field is visually cleared but when i enter some value into one of the user inputted fields(value1 or value2) the calculated field adds the entered number with the previous number that the field ccontained.
I tried many ways to solve this issue, but with no suuccess.... can someone please guide me through?
Thanks in advance.....

Here's a simple fiddle . Follow the link and take a look.
Basically, to have only number values in the user inputed fields, I used HTML5 number inputs, readily available in any newer browser.
<div ng-controller="MyCtrl">
<input type="number" ng-model="value1" />
<input type="number" ng-model="value2" />
<input type="text" ng-model="value1 + value2" />
<button type="button" ng-click="reset()">RESET</button>
</div>
And as for the javascript, here is my controller:
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', MyCtrl)
function MyCtrl($scope) {
$scope.value1 = '';
$scope.value2 = '';
$scope.value3 = '';
$scope.reset = function() {
$scope.value1 = '';
$scope.value2 = '';
$scope.value3 = '';
};
}
The three values are first initialized as empty strings, and on ng-click of the RESET button, they are nullified again.
NOTE: For the sake of simplicity I used number inputs instead of trying to implement some kind of javascript validation which I would suggest for production level. The point of my answer was just to explain the principle using the most basic concepts.

Related

ng-disabled on inputs from ng-repeat loop

I'm displaying inputs basing on array like this
<div data-ng-repeat="n in langInput.values">
<input type="text"
id="auction_name_{{n.selected}}"
class="form-control"
name="auction_name_{{$index}}"
data-ng-model="inputs.auction_name[$index + 1]"
data-ng-minlength="5"
data-ng-maxlength="60"
required />
<span data-ng-show="sellItem['auction_name_'+$index].$error.required">Wymagane!</span>
It also give's me ability of angularjs validation. Next after <form> is closed I want to create "next" button but I also want to do validation there so if user don't fullfill required inputs he will not be able to click it.
Array which I'm ng-repeating on is:
$scope.langInput = {
count: 3,
values: [
{
id: "1",
selected: "pl"
},
{
id: "2",
selected: "eng"
}
],
add: function () {
if (this.count < 7) {
this.values.push({id: this.count, selected: "eng"});
this.count += 1;
console.log(this.values);
}
},
remove: function () {
if (this.count > 2) {
this.values.pop();
this.count -= 1;
console.log(this.count);
}
}
};
I know I can use this ng-disabled directive however I don't know how I can check this inputs which are displayed in loop because its name is changing depending on $index of loop.
I've created plunker
My situation is that I know that I can disable button when some of element is invalid by ng-disabled="sellItem.$error" but in my form in real project I have this form much bigger and I have many ways of acomplishing form so in the end when user finish fullfilling form user still got some of inputs which are not even shown invalid.
So I can't use ng-disabled="sellItem.$error" because after user complete form he still got invalid inputs in background.
I also can not split form to many little forms because it will call 1 endpoint on submit.
What I did in real project is inject 3 different buttons and show them on correct step. Every of this button need to have ng-disabled to not let user to go to next step without completing step' inputs.
So intead of ng-disabled="sellItem.$error" I need to specify all inputs in ng-disabled of one step ( which is about 5 inputs ).
So it would look something like this:
ng-disabled="sellItem.first_input.$error &&
sellItem.second_input.$error && ..."
And I would do this but then I come to problem that I can't "loop" inside of ng-disabled and I want to "loop" inside it because names of inputs are generated by JS
name="auction_name_{{n.id}}"
they and not constant they change, user can add more inputs and delete them
at page start I have two inputs which after JS run are name="auction_name_1" and name="auction_name_2" (due to binding interpolated value) and then user can and third one name="auction_name_3"so I can't also hardcode them within ng-disabled.
I don't know how I can check this inputs which are displayed in loop because its name is changing depending on $index of loop.
Generally one stores the input as a property of the object in the array so that it stays with the object as its position in the array changes.
Also use the id property of the object:
<form name="sellItem" ng-submit="submit()">
<div data-ng-repeat="n in langInput.values">
<input type="text"
id="auction_name_{{n.selected}}"
class="form-control"
̶n̶a̶m̶e̶=̶"̶a̶u̶c̶t̶i̶o̶n̶_̶n̶a̶m̶e̶_̶{̶{̶$̶i̶n̶d̶e̶x̶}̶}̶"̶
name="auction_name_{{n.id}}"
̶d̶a̶t̶a̶-̶n̶g̶-̶m̶o̶d̶e̶l̶=̶"̶i̶n̶p̶u̶t̶s̶.̶a̶u̶c̶t̶i̶o̶n̶_̶n̶a̶m̶e̶[̶$̶i̶n̶d̶e̶x̶ ̶+̶ ̶1̶]̶"̶
data-ng-model="n.input"
data-ng-minlength="5"
data-ng-maxlength="60"
required />
<span data-ng-show="sellItem['auction_name_'+n.id].$error.required">Wymagane!</span>
<span data-ng-show="sellItem['auction_name_'+n.id].$error.minlength">Za krótkie!</span>
<span data-ng-show="sellItem['auction_name_'+n.id].$error.maxlength">Za długie!</span>
</div>
<button type="submit" ng-disabled="sellItem.$error">
{{Submit}}
</button>
</form>
Be sure to generate unique values for the id property.
Update
Added Submit button.
For more information, see
AngularJS Developer Guide - forms
AngularJS <form> Directive API Reference
AngularJS ng-submit Directive API Reference

Handle Number Input in Firefox via AngularJS

I'm running into a strange issue in Firefox that I hope someone can explain to me. I have an AngularJS controller with a method that is tied to ng-change on a variety of input controls in a form, including one that is marked as a number input. The logic of this method is that if any one of the bound scope variables is set properly, to set another scope variable to true. This is basically an attempt at form validation where any one (or more) of the inputs is required.
Example:
app.controller('test', function($scope) {
$scope.num = 0;
$scope.name = "";
$scope.valid = false;
$scope.inputChange = function() {
console.log('Input changed');
$scope.valid = ($scope.num > 0) || ($scope.name.length > 0);
}
});
And form:
<form name="numberTest" ng-app="myApp" ng-controller="test">
<input ng-model="name" name="name" type="text" ng-change="inputChange()"/>
<input type="number" ng-model="num" name="n" id="n" ng-change="inputChange()"/>
<input type="button" value="Go" ng-disabled="!valid"/>
</form>
This all works fine in Chrome, but in Firefox this ng-change handler is fired when non-numeric text is entered in the numeric input and the textbox itself does get this bogus data in it although the model is not updated. This leads to a confusing state where there is invalid data in the num textbox that is not bound to the AngularJS model but the user can click the button. Chrome does not present this problem as it does not render the non-numeric data in the input control.
How can I detect (and handle) this scenario? The input control is displaying text that is invalid and not bound to the binding model.
I am certainly open to alternative implementations to achieve this same effect. AngularJS version is 1.3.0.
Example plunker to run in Firefox to see the "bad" behavior
I ended up discovering the $valid attribute of these number inputs, and that seemingly satisfies my needs:
Returns true if empty
Returns false if non-numeric data is in the control
So, my updated button:
<input type="button" value="Go" ng-disabled="!valid || !numberTest.n.$valid"/>

addition function for input that comes within ng-repeat

Can someone please point me in the right direction or give me anything on how to make an addition function work with an input that will be created dynamically and is as long the ng-repeat ( which is mostly more than one ) ? I am having trouble on connecting the input by ng-model with the function, so couldn't accomplish anything.
the simplest form of can be like this...
<div ng-repeat="gameName in gameNames track by $index">
<p> {{gameName.title}}</>
<input type="number" >
</div>
Result : {{total}}
will be forever thankful.
First you need to add a ng-model in the input so angular can track it:
<input type="number" ng-model="gameName.value">
For a calculated field, add a method to your controller
$scope.total = function() {
var total = 0;
angular.forEach($scope.gameNames, function(gameName, key) {
total = total + gameName.value;
});
and then bind to it directly. It will know when it needs to recalculate as its constituent values change.

Can I change dyanmic javascript variable depending on user form input?

My question here is if there is a way to change the dynamic price calculation depending on the name a user enters in the input field.
I have code that works very well for calculating a dynamic price in an html form. Here is the code:
Using this input:
<input class="typeahead" type="text" placeholder="Amount" name="Amount"/>
My Javascript then calculates price:
jQuery("input[name='Amount']").change(function () {
if (isNaN(parseFloat(this.value)) || !isFinite(this.value)) {
jQuery(this).val('');
return false;
}
var calc = parseFloat(this.value) * 0.95;
jQuery(this).parents("form").find("input[name='price']").val(calc);
});
That by itself works fantastic. It calculates the amount by .95 and then assigns that value as price.
If I add this into the form:
<input class="stores typeahead" type="text" placeholder="Stores" name="name"/>
What can I do here to be able to calculate the price at different values depending on the store name. For example, if someone enters McDonalds, I want it to calculate at .90. If someone enters Target, I want it to calculate at .92. The previous javascript cannot accomplish this because it calculates everything at .95 instead of being able to change depending on the store entered.
I would prefer to accomplish this with javascript because I'm not very skilled with php.
You can create a Javascript object for this.
var stores = {
"McDonalds" : .90,
"Target" : .92,
}
var storeName = jQuery(this).parents("form").find("input[name='name']").val();
console.log(stores[storeName]); //Output the store cost to console.
Though I think the jQuery lookup function is questionable. I'm sure there is a better way to select that textbox. But that's the general concept you're looking for.

jQuery prepopulate form fields from select box and calculate results

I am building a calculator form to allow people to calculate the cost of running electrical appliances. They can select an appliance, as an example, from a dropdown list and this should prepopulate the text fields with the figures necessary for the calculation. Here is the form:
<form action = "<?php echo $_SERVER['PHP_SELF']; ?>" method = "POST">
<label>Appliance</label>
<select id="list" >
<option value="select">Select</option>
<option value="dishwasher">Dishwasher</option>
<option value="iron">Iron</option>
</select>
<label>Watts</label> <input name="watts" /><br>
<label>Hours</label> <input name="hours" /> <br>
<label>Price</label> <input name="price" /> <br>
<label>Number</label> <input name="number" /> <br>
<label>Total</label> <input name="total" value="" id="total"></input>
</form>
When a user selects an appliance I want the input fields to be filled something like this:
case 'dishwasher':
$('input[name="watts"]').val('1200');
$('input[name="hours"]').val('20');
$('input[name="price"]').val('10');
$('input[name="number"]').val('1');
Then do some calculation on the figures:
kilowatts = watts / 1000;
kwhours = kilowatts * hours;
costpounds = kwhours * price / 100;
total = costpounds * number
and put the total into the total field in the form, the idea is to also allow the user to change the figures, or even just add their own, in the form and the total updates accordingly. I can get all the individual bits to work, but don't know jquery well enough to put it all together. Help would be greatly appreciated. Thanks!
Here is some javascript / jquery to get you started. There are more efficient ways, but those are very confusing for someone just learning.
//when the document is finished being rendered, this fires
$(document).ready(function(){
//if the user changes the value in the select dd, this fires.
$('#list').change(function(e){
changeInputValues(this.val());
});
// standard JS function to set the input values with defaults for a given drop down. your idea ;)
function changeInputValues(ddValue){
//put your Case 'dishwasher' code here, one case for each Drop down value
//$('input[name="watts"]').val('1200');
//$('input[name="hours"]').val('20');
//$('input[name="price"]').val('10');
//$('input[name="number"]').val('1');
//recalculate the figures
recalculate();
};
// when someone changes an input, but not the Drop Down, we have that on already.
$('input').not('select').change(function(e){
recalculate();
});
function recalculate(){
// get the current values, then do your math
//var currentWatts = $('input[name="watts"]').val();
//var currentHours = $('input[name="hours"]').val();
//....
//var total = 0;
// do more math... whatever you want
//set the 'visible' value
$('input[name="total"]').val(total)
};
});
So basic structure is 2 functions.
Called when the "appliance" select is changed. Takes all the values of the item selected by grabbing the id like $(this)find('selected').attr('id')*. Once you have the id of the select appliance you can use it to pull the correct values from your appliance arrays and then it's easy to $(this).find('name_of_filed').text("value from the array") with a little for each loop.
called when any other field is onChanged (or you can make an update button in case it's annoying to have it constantly updating while you are making multiple changes). Also called at the end of function 1. Takes all the values from the fields, does calculation, inserts into "total" field.
you can certainly break this down much further to smaller pieces if you want it to be more easily edited in the future and to reuse any of this code but if it's going to be a one of then I wouldn't bother splitting it much more than this.
I can get a lot more specific if need be but I figure it's better for you to try and figure specifics out to learn as you go and we here at SO can answer specific questions as you go.
*may not be actuall correct code. I'm lazy and you will learn more this way! ;)

Categories

Resources