I have a form where I'm taking a input and according to that creating a number of input boxes. The javascript code is given below for that.
for(i = 1; i <= c; i++) { //c = total input count
block = block + '<div class="row">'+
'<div class="form-group col-lg-12">'+
'<input id="name" ng-model="new.var'+i+'name" type="text" class="form-control">'+
'<input id="type" ng-model="new.var'+i+'type" type="text" class="form-control">'+
'</div>'+
'</div>';
}
document.getElementById("vars").innerHTML = block;
Above code is working fine & ng-model are getting generated dynamically fine, like new.var1name , new.var1type , new.var2name , new.var2type and so on.
But how to get those variables in my controller?
If I generate those variables in my controller like below then its giving error that it cant find 'name'.
var var1 = [];
for(i = 1; i <= c; i++) { //c = total input count
var item = {};
console.log('var'+i+'name', 'var'+i+'unit');
item['name'] = $scope.new.var+i+name;
item['type'] = $scope.new.var+i+type;
var1.push(item);
}
console.log(JSON.stringify(var1));
so I have used like below but now no error is there but the var1 is empty.
var var1 = [];
for(i = 1; i <= c; i++) {
var item = {};
console.log('var'+i+'name', 'var'+i+'type');
item['name'] = $scope.new['var'+i+'name'];
item['type'] = $scope.new['var'+i+'type'];
var1.push(item);
}
console.log(JSON.stringify(var1));
Please anyone help me to find what I'm doing wrong or is it possible to do???
I would suggest that, rather than generate the html in your controller, you write this html in your view, and repeat it using angular's ng-repeat directive: https://docs.angularjs.org/api/ng/directive/ngRepeat. Something like this (not tested):
<div ng-repeat="item in c track by $index">
<input id="name" ng-model="name[$index]" type="text" class="form-control">
<input id="type" ng-model="type[$index]" type="text" class="form-control">
</div>
You should then be able to access the name and type arrays from $scope within your controller. If 'c' is the ng-model for your original input (which defines the number of times to repeat) then new fields should get added dynamically if this the desired functionality?
EDITED
in your controller
$scope.c = 5;
$scope.getNumber = function(num) {
return new Array(num);
}
in your view
<div ng-repeat="i in getNumber(c) track by $index">
<input id="name" ng-model="name[$index]" type="text" class="form-control">
<input id="type" ng-model="type[$index]" type="text" class="form-control">
</div>
use $scope['new.var'+i+'name']
there are two ways accessing object property in JavaScript:
if you know the name, you can do $scope.new.var1name
if the name is dynamic, which is your case, you can use the bracket syntax $scope['new.var'+i+'name']
Related
I am trying to dynamically assign variable names using the user's input. For example:
var input = document.querySelector('input');
for(var i = 0; i < 10; i++){
var newVariableName = //input.value;
}
Any help would be very much appreciated.
Thank you,
Scratch Cat
Everything in JavaScript is an object. The way JavaScript works, you can add properties to objects in two ways:
Specify them the fixed way (e.g. obj.propertyName = 'Value')
Specify them using array notation (e.g. obj[propertyName] = 'Value'). In this case, note that propertyName is a string value.
In both cases, the result will be exactly the same. You could retrieve those properties likewise, e.g. obj.propertyName and obj[propertyName]. Both will return 'Value'.
In your case, #LuudJacobs's suggestion about using the window object will most probably do the trick...
You can use array in which the keys will be the input values and the value would be anything you want.
html
<form>
<input type="text" value="demo1" class="example"><br />
<input type="text" value="demo2" class="example"><br />
<input type="text" value="demo3" class="example">
</form>
js
First you declare array
var a = new Array();
Then you use for loop to assign key names to array which will be the input values
for(var i = 0; i < 3; i++){
a[x[i].value] = x[i].value;
}
Finally you can use those key names to access the values
alert(a['demo1'] + ' ' +a['demo2'] + ' ' + a['demo3']);
Here is a link to an example
https://jsfiddle.net/309fpsjn/1/
<html>
<form>
<input type="text" value="demo1" class="example"><br />
<input type="text" value="demo2" class="example"><br />
<input type="text" value="demo3" class="example">
</form>
<script>
var x = document.querySelectorAll(".example");
var a = new Array();
for(var i = 0; i < 3; i++){
a[x[i].value] = x[i].value;
}
alert(a['demo1'] + ' ' +a['demo2'] + ' ' + a['demo3']);
</script>
</html>
I have a field in my page named as "myField" Now this is dynamic So there are 2 cases i.e. it can be just 1 field as;
<input type="text" name="myField" />
OR there can be 2 fields as below;
<input type="text" name="myField" />
<input type="hidden" name="myField" />
I use the following code to access the value in JS;
document.forms[0].myField[0].value
However, this does not work if there is only 1 field (as in the first case)
How do I write dynamic JS code to handle the same? It should be cross browser compatible.
document.getElementById("btn").addEventListener("click", function() {
var texts = document.getElementsByName("n");
var sum = "";
for( var i = 0; i < texts.length; i ++ ) {
sum = sum + texts[i].value;
}
document.getElementById("sum").innerHTML = sum;
});
<input type="text" name="n"/>
<input type="text" name="n"/>
<p id="sum"></p>
<button id="btn"> Get Sum</button>
or Visit :How get total sum from input box values using Javascript?
On first glance of that particular example, it seems odd that those two fields have the same name. Normally one would expect the same name for fields that are mutually-exclusive, or that are the same type and form a list.
But you can still work with them: I wouldn't use the automatic properties, since as you've discovered they're inconsistent (document.forms[0].myField will be the field when there's only one, but a collection of fields with the same name if there's more than one). I'd use querySelectorAll:
var fields = document.querySelectorAll('[name="myField"]');
fields will reliably be a list. You can access the elements of that list using fields[0] and such, and get the length from fields.length.
var fields = document.querySelectorAll('[name="myField"]');
for (var n = 0; n < fields.length; ++n) {
console.log("fields[" + n + "].value: ", fields[n].value);
}
<input type="text" name="myField" value="the text field"/>
<input type="hidden" name="myField" value="the hidden field"/>
I have the below directive, which outputs the number and the corresponding string value from the array data.
var app = angular.module("test",[]);
app.controller("Ctrl1",function($scope){
$scope.range = 5;
$scope.data = ['a','b','c','d','e',];
});
app.directive("myDirective", function(){
return {
restrict: "EA",
scope: true,
template: "<div ng-repeat='n in [] | range:range'>{{n + 1}} - {{data[n]}}</div>"
};
})
.filter('range', function() {
return function(input, total) {
total = parseInt(total);
for (var i=0; i<total; i++)
input.push(i);
return input;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test">
<div ng-controller="Ctrl1">
<label>Edit range </label> <input ng-model="range" /><br>
<label>edit data </label> <input ng-model="data" /><br>
<my-directive></my-directive>
</div>
</div>
This runs as expected on load however when the user edits the ng-model="data" the output breaks as it is including the , as an item in the array.
What is the best way to get this working so that when the user updates the data the directive still treat the array like it did initially? (I am happy to either comma seprate items in data or another method such as | if required.)
The better way would be to have a function to push and pop the input data in the array. Something like the following :
HTML :
<input type="text" ng-model="inputdata" ng-click="pushDataInArray(inputdata);"></input>
//And similarly have a function to pop the data from whichever index from the array.
JS:
$scope.pushDataInArray = function(inputdata){
$scope.data.push(inputdata);
};
This would be a better approach IMO.
<input ng-model="data" /> will write the new value into a string an not an array. you need to split the string into an array See http://www.w3schools.com/jsref/jsref_split.asp
I am looking for a way to add the following row of inputs using a button (and I've found plenty of examples) BUT most of them renames the name of html element (e.g. name = 'price1', name = 'price2') but my javascript references the element's id, making it erroneous when new rows are added. Some helps are appreciated.
JS Fiddle just to see the rows
https://jsfiddle.net/n4h5uwvk/
the HTML code
<form action = "" method = "POST">
<label>Item : </label>
<select id = 'item_name' name = 'item_name' onChange = 'listMatch(this);fieldCheck();'
>
<option value = "" disabled = "disabled" selected="selected">Please Select</option>
<?php
while($row = mysqli_fetch_assoc($result)){
echo "<option value = '".$row['PRODUCT_ID']."' data-price ='
".$row['UNIT_PRICE']."' >".$row['PRODUCT_NAME']."</option>";
}
?>
</select>
<label>Price : </label>
<input type = 'text' id = 'item_price' name = 'item_price' value = '' disabled/>
<label>Quantity : </label>
<input type = "number" id = 'quantity' name = 'quantity' max = "150" min = "0" onChange = 'multiplier(value)' disabled/>
<label>Sub-Total : </label>
<input type = "number" id = 'sub-total' name = 'sub-total' disabled value = ''/>
and the Javascript
<script>
//lists the price according to selected item
function listMatch(product){
var x = product.options[product.selectedIndex].getAttribute('data-price');
document.getElementById('item_price').value = x;
}
//un-disable quantity field after item is selected
function fieldCheck(){
document.getElementById('quantity').removeAttribute('disabled');
}
//var z = quantity*price
function multiplier(value){
var x = document.getElementById('item_price').value;
var y = value;
var z = x*y;
document.getElementById('sub-total').value = z.toFixed(2);
}
//clone fields on 'add field' button click
Updated :
I found a code to clone my forms well, but I encounter another problem. The clone will always duplicate values of the first row, I want to create child rows that have empty values. Any ways around this code?
//global variable for duplication identification
var count = 1;
//clone form for multiple entries
(function() {
$('#add').click(function() {
var source = $('form:first'),
clone = source.clone();
clone.find(':input').attr('id', function(i, val) {
return val + count;
});
clone.insertBefore(this);
count++;
});
})();
As you know id has to be unique and adding numbers to the cloned form elements to keep the ids unique seems overdoing it.
Names don't have to be unique though, so you can have different forms with elements with the same name. And they can be accessed easily by their names:
<form name="form_1">
<input name="firstName" type="text" />
<input name="lasttName" type="text" />
</form>
<form name="form_2">
<input name="firstName" type="text" />
<input name="lasttName" type="text" />
</form>
You can use the form name to access specific element, to access the input with name="firstName" in form_1 and form_2 you can use:
var firstName1 = document.form_1.firstName;
var firstName2 = document.form_2.firstName;
So it will be easy to distinguish between different forms, although their elements have the same structure and names. You just create a new form with name="form_X" and use innerHTML to add the cloned elements.
And to clone an element you can use .cloneNode(true); (or jQuery's clone()).
EDIT:
You still seem to think of it that you need to store everything in a variable, here's an example to do it all, and you can see it's much simpler than you think. I give these forms class="contactForm" to separate them from other forms there might be. we can clone 10 .contactForm and have 100 other forms in the page as well.
To get number of forms you can use $('form.contactForm').length
To empty text inputs inside new form you can use: newForm.find('input[type=text]').val("");
jsfiddle DEMO
I am trying to populate a total field with id- #appointment-total_amount using javascript/jquery. Referring this Jsfiddle add two fields together - Which is working fine.
I am using this code in my _form.php
<?php
$script = <<<EOD
$(function() {
$('#appointment-doctor_fee').keyup(function() {
updateTotal();
});
$('#appointment-discount').keyup(function() {
updateTotal();
});
var updateTotal = function () {
var input1 = parseInt($('#appointment-doctor_fee').val());
var input2 = parseInt($('#appointment-discount').val());
$('#appointment-total_amount').text(input1 + input2);
};
});
EOD;
$this->registerJs($script);
?>
But nothing is happening on the page.
I am not able to see what I am missing here.
Thanks.
Related HTML
<div class="form-group field-appointment-doctor_fee">
<label class="control-label" for="appointment-doctor_fee">Doctor Fee</label>
<input type="text" id="appointment-doctor_fee" class="form-control" name="Appointment[doctor_fee]" maxlength="10">
</div>
<div class="form-group field-appointment-discount">
<label class="control-label" for="appointment-discount">Discount</label>
<input type="text" id="appointment-discount" class="form-control" name="Appointment[discount]" maxlength="10">
<div class="form-group field-appointment-total_amount">
<label class="control-label" for="appointment-total_amount">Total Amount</label>
<input type="text" id="appointment-total_amount" class="form-control" name="Appointment[total_amount]" maxlength="10">
The error is in this line:
$('#appointment-total_amount').text(input1 + input2);
Should be:
$('#appointment-total_amount').val(input1 + input2);
Besides that add at least simple check for illegal numbers, because you will get NaN if one of the fields is empty or input value is not valid number. Some range limit will be good too.
var updateTotal = function () {
var doctorFee = parseInt($('#appointment-doctor_fee').val());
var discount = parseInt($('#appointment-discount').val());
var totalAmount = doctorFee + discount;
if (isNaN(totalAmount) || totalAmount < 0 || totalAmount > 100000) {
totalAmount = '';
}
$('#appointment-total_amount').val(totalAmount);
};
One more error is in script registration. Change to this:
use yii\web\View;
$this->registerJs($script, View::POS_END);
Otherwise it will be inserted before jQuery (and your script depends on it) and will not be working.
Registering scripts that way is not good practice, it's even mentioned in official documentation. Separate file and using assets is definitely better than struggling with dependencies and inserting js as string (the errors are hard to detect, no autocomplete, etc.).