only the first row were calculated automatically using jquery - javascript

i have this table that has a column for the edit button. a modal will pop up and the data from the row selected will show when the button is clicked.
so on my edit modal, i have 3 textboxes: Quantity, Consumed, and Available.
$('#edit-quant').keyup(function() {
var quant;
var consumed;
quant = parseFloat($('#edit-quant').val());
consumed = parseFloat($('#edit-consumed').val());
avail = quant - consumed || 0;
$("#edit-avail").val(avail);
});
$('#edit-consumed').keyup(function() {
var quant;
var consumed;
quant = parseFloat($('#edit-quant').val());
consumed = parseFloat($('#edit-consumed').val());
avail = quant - consumed || 0;
$("#edit-avail").val(avail);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="input-group mb-3">
<span class="input-group-text" style="color: #008080"><label>Quantity</label></span>
<input class="form-control" type="text" id="edit-quant" name="edit-quant" placeholder="Quantity" value="2"></i>
<span class="input-group-text" style="color: #008080"><label>Consumed</label></span>
<input class="form-control" type="text" id="edit-consumed" name="edit-consumed" placeholder="Consumed" value="3">
<span class="input-group-text" style="color: #008080"><label>Available</label></span>
<input class="form-control" id="edit-avail" type="text" name="edit-avail" placeholder="Available" value="4" readonly>
</div>
and when i try to change the values of the Quantity and Consumed and calculates its Available. only the first row of the table were working. the proceeding rows remains the same. how can i fix this?

I assume you have these repeated. You should not have an id attribute that is the same on any two or more elements on the same page. When you select an element by its id, the first element found with that value is going to be returned.
What you can do is make these into classes, then to get the fields, you can find the .closest(".input-group") which is wrapping all of your fields. From there, you can pull any of the fields by their given class. Alternatively, just use the name attribute on the fields and get rid of the id all together.
<div class="input-group mb-3">
<span class="input-group-text" style="color: #008080"><label>Quantity</label></span>
<input class="form-control" type="text" name="edit-quant" placeholder="Quantity" value="{{$med->med_quantity}}" ></i>
<span class="input-group-text" style="color: #008080"><label>Consumed</label></span>
<input class="form-control" type="text" name="edit-consumed" placeholder="Consumed" value="{{$med->med_consumed}}">
<span class="input-group-text" style="color: #008080"><label>Available</label></span>
<input class="form-control" type="text" name="edit-avail" placeholder="Available" value="{{$med->med_available}}" readonly>
</div>
I've removed the id attributes from the three fields. Now, when our event triggers, we'll find the group (parent DIV), and get each field with .find().
$('input[name = "edit-quant"], input[name = "edit-consumed"]').keyup(function()
{
var $group = $(this).closest('.input-group');
var quant = parseFloat($group.find('input[name = "edit-quant"]').val());
var consumed = parseFloat($group.find('input[name = "edit-consumed"]').val());
$group.find('input[name = "edit-avail"]').val(quant - consumed || 0);
});
Untested, but should work for you, or at least get you on the right track.

Related

Checkbox not working on checked to add values

I have created calculation system project with javascripts all things are good calculation done perfectly tax include perfectly but tax not included when I click on checkebox, it add when I type something in input field, I want values changes on when I clicked on checkbox and even when I type something
html
<div class="form-group row">
<div class="col-sm-6">
<input type="float" class="form-control form-control-user" id="BMS_qty" name="BMS_qty" placeholder="BMS Quantity">
<input type="float" class="form-control form-control-user" id="BMS_price" name="BMS_price" placeholder="BMS Price">
</div>
</div>
<div class="col-sm-6 form-check">
<input type="checkbox" id="tax" name="taxamount" value="0.17">
<label for="tax">Included Tax</label><br>
<label for="total_expenses1" style="text-align: right;">Total:- </label>
<span id="total_expenses1"></span>
</div>
javascript
$('input').keyup(function(){ // run anytime the value changes
var BMS_qty = Number($('#BMS_qty').val());
var BMS_price = Number($('#BMS_price').val());
if(document.getElementById("tax").checked) {
var tax = 0.17;
} else {
tax = 0;
}
var subtotal = BMS_qty * BMS_price;
var total = tax * subtotal;
$('#total_expenses1').html(total + subtotal); // add them and output it
// add them and output it
});
The problem is that the keyup() method will only act on an <input type="checkbox"> when the space key is pressed to activate it.
To avoid this kind of problem I'd suggest switching the code to react to input events (which covers any event in which the value/state of an <input> is changed).
One approach to solving the problem is below, with explanatory comments included:
// we select all <input> elements regardless of their type attribute,
// and bind the anonymous function of the on() method as the event-handler
// for the 'input' event:
$('input').on('input', function() {
// switching to the use of const to declare variables that shouldn't
// change after they've been defined, and we use parseInt() instead
// of Number() to convert those the entered-values into numbers
// supplying the radix (base) argument of 10 because we're working
// with base-10 numbers (this is largely a personal preference, I
// don't think there's a particular argument for, or against, this
// change):
const BMS_qty = parseInt($('#BMS_qty').val(), 10),
BMS_price = parseFloat($('#BMS_price').val()),
// here we use a conditional (ternary) operator, in which we
// assess - using the .is() method - whether the element with
// the id of "tax" is checked.
// If it is checked the value of tax is 0.17, if it is not
// the value is 0:
tax = $('#tax').is(':checked') ? 0.17 : 0;
// using let to declare variables that may need to change if
// the calculations/results need to be modified in production:
let subtotal = BMS_qty * BMS_price,
total = tax * subtotal;
// adding the values, andd writing it the element with an
// id equal to "total_expenses", though I've switched to using
// the text() method to avoid accidentally trying to insert any
// HTML elements in the future:
$('#total_expenses1').text(total + subtotal);
});
<div class="form-group row">
<div class="col-sm-6">
<input type="float" class="form-control form-control-user" id="BMS_qty" name="BMS_qty" placeholder="BMS Quantity">
<input type="float" class="form-control form-control-user" id="BMS_price" name="BMS_price" placeholder="BMS Price">
</div>
</div>
<div class="col-sm-6 form-check">
<input type="checkbox" id="tax" name="taxamount" value="0.17">
<label for="tax">Included Tax</label><br>
<label for="total_expenses1" style="text-align: right;">Total:- </label>
<span id="total_expenses1"></span>
</div>
JS Fiddle demo.
References:
JavaScript:
Conditional ("ternary") Operator.
parseFloat().
parseInt().
jQuery:
is().
on().
text().
You need to use on() to get events you need
I think, you also need to change Number() by parseInt()
$(document).on('keyup keypress keydown change', 'input[name="BMS_qty"], input[name="BMS_price"], input[name="taxamount"]', function(){ // or keypress I have the same result
var BMS_qty = parseInt($('#BMS_qty').val());
var BMS_price = parseInt($('#BMS_price').val());
if(document.getElementById("tax").checked) {
var tax = 0.17;
} else {
tax = 0;
}
var subtotal = BMS_qty * BMS_price;
var total = tax * subtotal;
$('#total_expenses1').html(total + subtotal); // add them and output it
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-group row">
<div class="col-sm-6">
<input type="float" class="form-control form-control-user" id="BMS_qty" name="BMS_qty" placeholder="BMS Quantity">
<input type="float" class="form-control form-control-user" id="BMS_price" name="BMS_price" placeholder="BMS Price">
</div>
</div>
<div class="col-sm-6 form-check">
<input type="checkbox" id="tax" name="taxamount" value="0.17">
<label for="tax">Included Tax</label><br>
<label for="total_expenses1" style="text-align: right;">Total:- </label>
<span id="total_expenses1">0</span>
</div>

textbox validation for number and required in repeating mode angular js

Please refer below link
https://plnkr.co/edit/9HbLMBUw0Q6mj7oyCahP?p=preview
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.NDCarray = [{val: ''}];
$scope.NDCadd = function() {
$scope.NDCarray.unshift(
{val: ''}
);
};
$scope.data = angular.copy($scope.NDCarray);
$scope.NDCcancel=function(){debugger
$scope.NDCarray=$scope.data;
}
$scope.NDCdelete = function(index) {
if(index != $scope.NDCarray.length -1){
$scope.NDCarray.splice(index, 1);
}
};
});
It contains the textbox with add button. I have added validation for number and required field, it is working fine. but when i click add button it will create another textbox with entered value that time it showing the validation message for all the textboxes , i don't want to show validation message for all the textboxes. need to show validation for corresponding textbox only. that means when i enter something wrong in second textbox it is showing message to that textbox only.refer below screenshot.
validation message displaying for all textboxes.that should display for only one textbox.
Working plnkr : https://plnkr.co/edit/f4kAdZSIsxWECd0i8LDT?p=preview
Your problem is in your HTML, to get independant fields you must :
Move outside the form of the ng-repeat
Provide a dynamic name using $index on your fields, because name is what make each fields independant on the validation.
Here is the final HTML from the plnkr i didn't touch at all the javascript :
<body ng-controller="MainCtrl">
<form name="myForm">
<div ng-repeat ="ndc in NDCarray">
<div class="col-sm-4 type7" style="font-size:14px;">
<div style="margin-bottom:5px;">NDC9</div>
<label>Number:
<input type="number" ng-model="ndc.value"
min="0" max="99" name="{{'input_'+$index}}" required>
</label>
<div role="alert">
<span class="error" ng-show="myForm.input.$dirty && myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.number">
Not valid number!</span>
</div>
<tt>value = {{example.value}}</tt><br/>
<tt>myForm['input_{{$index}}'].$valid = {{myForm['input_'+$index].$valid}}</tt><br/>
<tt>myForm['input_{{$index}}'].$error = {{myForm['input_'+$index].$error}}</tt><br/>
</div>
<div class="col-sm-4 type7 " style="font-size:14px;">
<div style="padding-top:20px; display:block">
<span class="red" id="delete" ng-class="{'disabled' : 'true'}" ng-click="NDCdelete($index)">Delete</span>
<span>Cancel </span>
<span id="addRow" style="cursor:pointer" ng-click="NDCadd()">Add </span>
</div>
</div>
</div>
<tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
<tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
</form>
</body>
Couple of changes:
If you add "track by $index" to your ng-repeat it will make each group of elements unique so that you don't have to worry about deriving unique names for elements.
Your validation on the number (myForm.ndcValue.$error.number) didn't work so I changed it to myForm.ndcValue.$error.max || myForm.ndcValue.$error.min
Also, you can throw an ng-form attribute directly on the div with your ng-repeat.
Like this:
<div ng-repeat="ndc in NDCarray track by $index" ng-form="myForm">
<div class="col-sm-4 type7" style="font-size:14px;">
<div style="margin-bottom:5px;">NDC9</div>
<label>Number:
<input type="number" ng-model="ndc.value" min="0" max="99" name="ndcValue" required>
</label>
<div role="alert">
<span class="error" ng-show="myForm.ndcValue.$dirty && myForm.ndcValue.$error.required">
Required!</span>
<span class="error" ng-show="myForm.ndcValue.$error.max || myForm.ndcValue.$error.min">
Not valid number!</span>
</div>
<tt>value = {{example.value}}</tt>
<br/>
<tt>myForm.ndcValue.$valid = {{myForm.ndcValue.$valid}}</tt>
<br/>
<tt>myForm.ndcValue.$error = {{myForm.ndcValue.$error}}</tt>
<br/>
</div>
Here's the working plunker.
I changed the input element name from "input" to "ndcValue" to be less confusing.

Angular hide inputs in ng-repeat table rows

How would i hide input elements and replace there value to the table rows , the inputs are dynamically created with push see below code :
view
ID LIKE TO REPLACE THE INPUTS WITH THE VALUE OF INPUTS IN THE TABLE ROWS
<tr class="odd gradeX" ng-repeat="choice in vm.choices">
<td>Add</td>
<td>save</td>
<td>
<div class="form-group">
<div class="input-group">
<input type="text" placeholder="Item Name" class="form-control" ng-model="choice.item_name"/>
</div>
</div>
</td>
<td>
<div class="form-group">
<div class="input-group">
<select data-ng-options='t.value as t.label for t in vm.invoice_item_type' ng-model="choice.item_type" >
</select>
</div>
</div>
</td>
contoller
vm.choices = [];
vm.addNewChoice = function() {
var newItemNo = parseInt(vm.choices.length+1);
vm.choices.push({});
};
vm.saveChoice = function() {
var lastItem = vm.choices.length-1;
------ What to do here ------
};
Ok, the easiest way to do this would be probably something like this:
Add additional field to every choice object saying if it's saved or not
Add two <td>s for every choice, one with plain text and one with input and show/hide them depending on extra parameter' value.
Something like this:
<tr class="odd gradeX" ng-repeat="choice in vm.choices">
<td>Add</td>
<td>save</td>
<td ng-hide="choice.saved">
<div class="form-group">
<div class="input-group">
<input type="text" placeholder="Item Name" class="form-control" ng-model="choice.item_name"/>
</div>
</div>
</td>
<td ng-show="choice.saved">
<div class="form-group">
<div class="input-group">
<input type="text" placeholder="Item Name" class="form-control" ng-model="choice.item_name"/>
</div>
</div>
</td>
<!-- rest of your row goes here -->
</tr>
And in controller:
vm.choices = [];
vm.addNewChoice = function() {
var newItemNo = parseInt(vm.choices.length+1);
vm.choices.push({}); // we don't need to set `saved` property explicitly since undefined will be resolved to false
};
vm.saveChoice = function(choice) {
var lastItem = vm.choices.length-1;
choice.saved=true;
// probably some extra logic related to saving
};
Note that I've added parameter to saveChoice method - you need to know which choice to save.
Also, I think that button for adding new choice should be moved outside of the table - adding new item is not related to any existing item.

Put all values from input fields into an array and sort them

for my RPG sessions I want to create an Initiative helper, so I have 2 input fields, number+text where number is the modifier to the
d20 roll and text is the name of the subject (player or npc) -> example of the html (bootstrap components) (I have 6 of these rows so 12 number/text input pairs in total):
<div class="row">
<div class="col-lg-6">
<p>Modifier + Player</p>
<div class="input-group">
<span class="input-group-addon">
<input type="number" min="-5" step="1" placeholder="0">
</span>
<input type="text" class="form-control" placeholder="player1">
</div>
</div>
<div class="col-lg-6">
<p>Modifier + NPC</p>
<div class="input-group">
<span class="input-group-addon">
<input type="number" min="-5" step="1" placeholder="0">
</span>
<input type="text" class="form-control" placeholder="monster1">
</div>
</div>
</div>
Currently I read all the values on click of a button into an object but that is not the optimal base to work with:
var subjects = {};
$("#create").click(function() {
subjects.mod = $("input[type=number]").map(function() { return this.value; }).get();
subjects.name = $("input[type=text]").map(function() { return this.value; }).get();
});
because now I have ONE Object containing all the numbers and names in an array
Object {
mod=[12],
name=[12]
}
but I need both properties coupled into 1 object:
object1 {
"name":"player1",
"iniNumber": 17
},
object2 {
"name":"npc1",
"iniNumber": 10
},
...
I have a function to roll d20 + add the modifier for the final initiative value, but I am too stupid to solve the existing problems...
My current problems:
How do I create coupled Number+Name objects from the input fields, which selector/function to use?
How do I sort it descending? (I suppose I can do that myself as soon as 1) is corrected)
I hope this is what you're looking for.
// At first there was nothing.
var npcs = [];
// Someone eventually interacted with reality.
$('#create').click(function(){
// For every row in now... (You should add another class because you only want npc rows)
$('.row').each(function(i, $row){
// Create object from inputs of a specific row from this dimension.
var newNpc = {
name: $('input[type=text]', $row).val(),
iniNumber: $('input[type=number]', $row).val()
};
// Add object to array to fill our insecurities.
npcs.push(newNpc);
});
});

Knockout foreach bound to value in inputfield

I want to autogenerate a number of labels on the bottom of my page based on what someone fills in in an inputfield.
So when someone fills in "2", I want 2 labels to pop up, preferable when he typed it without leaving the inputfield or anything.
This is what I have:
HTML
<div class="form-group">
<label class="control-label" for="if_aantalMensen">
Hoeveel extra mensen wil je inschrijven?
</label>
<div>
<input type="text" class="form-control" id="if_aantalMensen" name="if_aantalMensen"
data-bind="textInput: aantalMensen">
</div>
</div>
<div data-bind="foreach: aantalMensenArray" class="form-group">
<label><span data-bind="text: $index"></span></label>
</div>
Javascript
var vm = {
aantalMensen: ko.observable(0),
aantalMensenArray: ko.computed(function() {
var fields = [];
for (var i = 0; i < self.selectedNumberOfFields(); i++) {
fields.push(new Parameter());
}
return fields;
})}
It works if I just make "aantalMensenArray" into an observableArray that already has values in it. However, I can't get it to change the amount of labels shown.
Use valueUpdate:'afterkeydown'
"http://jsfiddle.net/dpa6zk9j/"

Categories