Add new columns with specific ng-model to HTML table - javascript

So I am trying to add additional columns to a table inside a form. Adding the columns themselves is not that difficult but I don't know how to go about setting their ng-models.
This is my current code:
(HTML)
<button ng-click="add()" type="button">+ column</button>
<table>
<thead id="inputtablehead">
<th class="theadlabel">(in 1.000 EUR)</th>
<th>{{startyear}}</th>
<th class="NBBCodesHeader">NBB Codes</th>
<th>Source</th>
</thead>
<tbody class="input">
<tr>
<td>number of months</td>
<td>
<input ng-model="input{{startyear}}.NumberMonths" type="text" class="{{startyear}}" required>
</td>
<td class="NBBCodes"></td>
</tr>
<tr>
<td>Fixed assets</td>
<td>
<input ng-model="input{{startyear}}.FixedAssets" class="{{startyear}}" type="text" required>
</td>
<td class="NBBCodes">20/28</td>
</tr>
<tr>
<td>Inventory</td>
<td>
<input ng-model="input{{startyear}}.Inventory" class="{{startyear}}" type="text" required>
</td>
<td class="NBBCodes">3</td>
</tr>
</table>
(JS)
angular.module("inputFields", []).controller("MyTable", function ($scope) {
$scope.startyear = new Date().getFullYear();
var nextyear = new Date().getFullYear() - 1;
$scope.add = function () {
$(".NBBCodesHeader").before("<th>"+nextyear+"</th>");
$(".input .NBBCodes").before('<td><input class='+nextyear+' type="text" required></td>');
nextyear--;
};
});
So in my JS the <input class='+nextyear+' type="text" required> should become something like <input ng-model="input'+nextyear+'.NumberMonths" class='+nextyear+' type="text" required> for the <td> element added next to the 'number of months' row.
I was thinking to give ea row an id in the form of NumberMonths and then look up the id when adding the column.
So my question would be: is this a valid way to do it and how would I get this id? Or am I overthinking it and is there an easier way to do this?

Use standard javascript [] object notation for variable property names.
<input ng-model="input[startyear].Inventory"

You shouldn't do DOM manipulations from a controller. It's not a good practice when working with AngularJS. A good rule to remember that is: don't use jQuery. It's a common mistake when starting working with AngularJS. And, in case you would be completely sure that you need to modify the DOM, do it always from a directive.
About your problem, maybe you can base your solution in create a data structure in your controller (a Javascript Object), and render it through a ng-repeat in your template. This way, if you modify the object (adding a new column), the template will be automatically updated.

Related

How to execute a function with different arguments while having multiple ID's in javascript?

I have a table showing me two parameters. What I would like to do is change the value of each of these parameters when a button is clicked. So each parameter has its own button with its own specific Ids (made with jinja2). for the value to be changed, I have to take the name of the parameter as an argument in a function, please look at the below picture:
my actual setup
So I have my input box and my button to be clicked:
<td> <input type=number size=5 id="{{key}}"> </td>
<td> <button onClick="change('{{key}}')" name="{{key}}">change value</button> </td>
the hard part is that, the change has to be made by executing a python script, so my function is described as :
function change(key){
$.getJSON($SCRIPT_ROOT + '/_change_value', {
a: $('input[name="key"]').val(),
b: $('button[name="key"]').val()}, function(data) { alert("Value was changed to " + data.result);});
}
For testing purpose I just made a python function that will return a only, to check if all went good, but unfortunately.
#app.route('/_change_value')
def change_value():
a = request.args.get('a', 0, type=int)
b = request.args.get('b', 0, type=int)
return jsonify(result=a)
a is returned as 0 always... I'm glad if someone can help me with this
I'm pretty sure the value key is not passed. Thanks a lot in advance
Edit: I made a mistake posting this question, id is present instead of name for the input, but still that did not resolve my problem...
Here you go with a solutio https://jsfiddle.net/1dvjqy11/
$('button').click(function(){
var a = $(this).closest('tr').find('input[type="number"]').val();
var b = $(this).closest('tr').find('td').first().html();
console.log(a, b);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>Parameter</th>
<th>Value</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>GPS_Inject_to</td>
<td>127</td>
<td>
<input type="number" size=5 />
</td>
<td>
<button>
Change Value
</button>
</td>
</tr>
<tr>
<td>RPM2_SCALING</td>
<td>1</td>
<td>
<input type="number" size=5 />
</td>
<td>
<button>
Change Value
</button>
</td>
</tr>
</tbody>
</table>
I've used jQuery closest to get the parent tr and used jQuery find method to find the child elements.
Hope this will help you.

accessing object that is creating from a form submission

I am in the process of learning angular. I've created a simple HTML form and want that submission to create an object that I can access in other tables.
Code from 1 row of the HTML table/form
<tr>
<td>Q1</td>
<td><input type="number" ng-model="stateAid.WADM_Q1" placeholder="0"></td>
<td><input type="text" ng-model="stateAid.Foundation_Aid_Q1" placeholder="$0.00" class="currency"></td>
<td><input type="text" ng-model="stateAid.Salary_Q1" class="currency" placeholder="$0.00"></td>
<td><input type="text" ng-model="stateAid.Transport_Q1" class="currency" placeholder="$0.00"></td>
<td> {{ final_total_Q1 | currency }} </td>
<td></td>
<td></td>
<td></td>
</tr>
Angular Code:
app.controller('StateAidTable',function($scope) {
$scope.master={};
$scope.update =function(stateaid){
$scope.master = angular.copy(stateaid);
$scope.WADM_q1 = stateaid.WADM_Q1;
};
since the stateaid object has been copied to the $scope.master, does that mean that the master is now the object that I use to access the object's properties in the template. Thanks for the help!
Working absolutely fine link for the solution i have performed it for Q1, you can do it similarly for rest of them: http://plnkr.co/edit/Aabu35evC5GVhfuVLOHA?p=preview
$scope.update = function(stateaid) {
debugger
console.log($scope.stateAid.Foundation_Aid_Q1);
$scope.final_total_Q1=parseInt($scope.stateAid.Foundation_Aid_Q1+$scope.stateAid.Salary_Q1+$scope.stateAid.Transprot_Q1);
console.log($scope.final_total_Q1)
$scope.master = angular.copy(stateaid);
return $scope.master;
};

Real time calculation with PHP & array

For a client i'm currently working on their new system. In this system they can create bookings/invoices and send them to their clients.
On 1 page my client is needed to fill in the price for each container in the qoutation. My client asked me to make a new table column below the container columns with the total prices for all containers. I want to do this real time, so when my client fills in the prices the total price changes.
The only problem I stumble on is this:
I currently have PHP/MySQL function that collect all the containers from a certain quotation out of the database. With a while loop I create the needed html code for each of the containers. I made the input fields (where they fill in the prices) an array by naming the input fields like this:
<td>€ <input type="text" name="msg_container['.$i.'][ocean_freight]" value="'. $quote['ocean_freight'].'" style="width: 100px;" /></td>
The $i variable get's count up for each loop. It starts by 0 and ends when there are no containers left.
To make things a bit more detailed I have created a jsfiddle how the currently page looks like: https://jsfiddle.net/cwfmqbqv/
Now I'm not an expert in javascript so I'm stuck at this point. Long story short, how am I able to calculate all the values in the array in real time?
I've made a simple addition to your fiddle.
It's not complete as I only have time to make one for the Ocean Freight.
JSFiddle
$(document).ready(function() {
$(".oceanIn").keyup(function() {
var total = 0.0;
$.each($(".oceanIn"), function(key, input) {
if(input.value && !isNaN(input.value)) {
total += parseFloat(input.value);
}
});
$("#oceanTotal").html("Total: " + total);
});
});
Also I added some class and id to some of your elements to make it work.
Note
For this one, I used keyup but feel free to use different events like change or blur, or whatever fits your needs.
You should have tried to learn the basics of Javascript before you went and looked for a client.
Also, I think you're confused between a column and a row.
What you want is written in pure js in the following update to your jsfiddle:
JSFiddle
The principal concept here was using the change event on inputs. Furthermore, I didn't change the naming of your inputs but consider better conventions.
In the total function, we get a type of columns we're dealing with (using custom attributes is better than just using input names. eg: column-type="thc") and calculate the total number of each related input.
It uses Regular Expression (RegExp) in your case to find the right column out of input names. Mind that ~~ is just a simple hack for text to integer conversion in JavaScript.
Next we find all inputs and attach an event listener using addEventListener to each for the change event type. In this delegate, we find the appropriate input for total function and span IDs corresponding the column the input represents, again using RegExp but this time implicitly. Then change the corresponding span based on the total return value;
This is similar to the first answer, but more complete, and the addition fires on keyup instead of on blur. It applies to all the columns without needing to create separate functions for each. Here's the fiddle.
Javascript
$(function(){
$(".ocean-input, .bunker-input, .thc-input, .road-input").on("keyup", function()
{
var total = 0;
$("." + $(this).attr('class')).each(function()
{
total += parseFloat($(this).val().replace('', 0).replace(',', '.'));
});
$("#" + $(this).data("total-id")).html(total.toString().replace('.', ','));
});
});
HTML
<table width="100%" border="0" cellspacing="0" cellpadding="0" style="font-family:Arial, sans-serif; color:#000; font-size:12px;">
<thead>
<tr>
<th width="50">Amount</th>
<th>Type</th>
<th>Weight (p/u)</th>
<th>Shipping owned</th>
<th>Ocean Freight</th>
<th>Bunker Surcharge</th>
<th>THC</th>
<th>Road transport</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Container Type 1</td>
<td>1000</td>
<td>No</td>
<td>€ <input type="text" class="ocean-input" data-total-id="ocean-total" name="msg_container[0][ocean_freight]" value="" style="width: 100px;"></td>
<td>€ <input type="text" class="bunker-input" data-total-id="bunker-total" name="msg_container[0][bunker_surcharge]" value="" style="width: 100px;"></td>
<td>€ <input type="text" class="thc-input" data-total-id="thc-total" name="msg_container[0][thc]" value="" style="width: 100px;"></td>
<td>€ <input type="text" class="road-input" data-total-id="road-total" name="msg_container[0][road_transport]" value="" style="width: 100px;"></td>
</tr><tr>
<td>1</td>
<td>Container Type 2</td>
<td>2500</td>
<td>No</td>
<td>€ <input type="text" class="ocean-input" data-total-id="ocean-total" name="msg_container[1][ocean_freight]" value="" style="width: 100px;"></td>
<td>€ <input type="text" class="bunker-input" data-total-id="bunker-total" name="msg_container[1][bunker_surcharge]" value="" style="width: 100px;"></td>
<td>€ <input type="text" class="thc-input" data-total-id="thc-total" name="msg_container[1][thc]" value="" style="width: 100px;"></td>
<td>€ <input type="text" class="road-input" data-total-id="road-total" name="msg_container[1][road_transport]" value="" style="width: 100px;"></td>
</tr> </tbody>
<tfoot>
<tr>
<th width="50"></th>
<th></th>
<th></th>
<th></th>
<th>Total: €<span id="ocean-total"></span></th>
<th>Total: €<span id="bunker-total"></span></th>
<th>Total: €<span id="thc-total"></span></th>
<th>Total: €<span id="road-total"></span></th>
</tr>
</tfoot>
</table>

Set the value in html text box and dropdown with Angular JS

In html we use to write like this <input type="text" value="8">. I am facing two problems while I am doing it using angular js tags.
I want to set some value which I am taking from database like value=8.
And I am using one drop down in this form. I want to auto select some value which is set in database.
<form id="attendanceSheet" name="attendanceSheet" ng-submit="fillUpTimeSheet(attendanceSheet.$valid)" >
<table ng-table="tableParams" class="table">
<tr ng-repeat="resource in resources">
<td data-title="'Working Hours'" style="text-align:center" ng-if="resource.isBillable == 1">{{resource.billable_hours}}h <input type="number" style="width: 55px;" min="0" max="8" ng-init="timeSheet[$index] = {}" ng-model="timeSheet[$index].billableHour" required></td>
<td data-title="'Non Billable Resource'" style="text-align:center" ng-if="resource.isBillable == 1"><select data-ng-options="o.resource_name for o in nonBillableResources" style="width: 150px;" ng-model="timeSheet[$index].nonBillableResource"></select></td>
</tr>
</table>
</form>
To set the value I tried like this .. value="resource.id" OR ng-init="timeSheet[$index] = {resource.id}"
Please I need help.

Angular JS object as ng-model attribute name

I'm creating a dynamic angular js application wherein I want to use a textbox as a searchtext for the filter of a table. Here's a preview on what I am doing:
As of now, my code looks like this
<table>
<thead>
<tr class="filterrow">
<td data-ng-repeat="col in items.Properties">
<input id="{{col.DatabaseColumnName}}" type="text"
data-ng-model="search_{{col.DatabaseColumnName}}"/>
<!-- Above Here I want to dynamically assign the ng-model based on Databasecolumnname property-->
</td>
</tr>
<tr>
<th data-ng-repeat="col in items.Properties">{{col.ColumnTitle}}</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="content in items2.Contents | filter: search_{{col.DatabaseColumnName}}: search_{{col.DatabaseColumnName}}">
<td data-ng-repeat="col in items.Properties">
{{content[col.Databasecolumnname ]}}
</td>
</tr>
</tbody>
</table>
I already tried the approach of using $compile but I wasn't able to implement it. Any ideas in an approach? Thanks!
EDIT: Plnkr - plnkr.co/edit/5LaRYE?p=preview
You can do this by setting a base object for your ng-Models. So in your controller you will have:-
$scope.search = {};
and in your view do:-
<input ng-attr-id="{{col.DatabaseColumnName}}" type="text"
data-ng-model="search[col.DatabaseColumnName]"/>
With this your dynamic ng-model will be assigned to the search base object, ex:- if col.DatabaseColumnName is col1 then ngModel would be $scope.search.col1

Categories

Resources