AngularJS add row in table - javascript

I use angularJS and I have one table on my page, I made one button to add row with input fields. My solution work good for adding rows and value of input fields in form, but doesn't work well where I need to delete particular row. I use one function for form, and another for adding and deleting rows.
It's like this:
<div ng-init="tmplCtr.newPeople()">
<div class="col-lg-12">
<input name="postsubmit" class="btn btn-default btn-sm" type="submit" value="Save table" ng-click="tmplCtr.newTable(tmplCtr.table)" />
<button class="btn btn-default btn-sm" ng-click="tmplCtr.editRow()">Add row</button>
</div>
<form name="peopleForm" novalidate>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th class="place-name">Name</th>
<th class="place-value">Lastname</th>
<th class="place-options">Options</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="people in tmplCtr.peoples">
<td class="place-name"><input type="text" name="" class="form-control" autocomplete="off" ng-model="tmplCtr.peoples.values[$index].name"></td>
<td class="place-last"><input type="text" name="" class="form-control" autocomplete="off" ng-model="tmplCtr.peoples.values[$index].lastname"></td>
<td class="place-options"><button class="btn btn-danger btn-md btn-delete" ng-click="tmplCtr.editRow($index)">Delete</button></td>
</tr>
</tbody>
</table>
</div>
</form>
When I press button add row I get row, but when I press delete row I delete row from screen but last row in array, not by index. Beside that also value of that row is not deleted from form scope. Function is:
function editRow(item) {
if(item == undefined) {
vm.peoples.push({});
} else {
vm.peoples.splice(item,1);
}
}
Can anyone help me?

I think its better to make two functions, the first one is for adding items, and the second one is for deleting like below:
function addEmptyItem(){
vm.peoples.push({});
}
function deleteItem(index){
vm.peoples.splice(index, 1);
}
Then in your view you can change tmplCtr.editRow($index) --> tmplCtr.deleteItem($index)
Furthermore it is strongly advised to use this syntax person.name etc in your repeat directive.
EDIT:
This is not tested by the way...

Related

display:'table' is not working as it supposed to be

I want the table to be visible only after the submit button clicks. But it's not staying on the screen as it is supposed to be. Once I click the submit button, the table comes up for a second and then again becomes invisible. Please let me know what I am doing wrong in my code. Also please let me know if there is any other way to do it.
index.html
<form action="#" id="form" method="post">
<div style="margin-left: 2rem;">
<!-- <input class="btn btn-primary" type="submit" value="Submit" id="btn" onclick="hide()"> -->
<input class="btn btn-primary" type="button" value="Submit" id="btn" onclick="hide()">
</div>
</form>
<div style="margin-top: 4rem; display: flex; justify-content: center; align-content: center;">
<table style="display: none;" id="table">
<tbody>
<tr>
<th scope="row">Profile No. : </th>
<td>{{ProfileNo}}</td>
</tr>
<tr>
<th scope="row">Name : </th>
<td>{{Name}}</td>
</tr>
</tbody>
</table>
</div>
<script>
function hide() {
document.getElementById("form").submit();
let table = document.getElementById("table");
if (table.style.display === 'none') {
table.style.display = 'table';
}
}
</script>
You need to use AJAX for this to work. If you do it like this, the submit button performs a POST request to the server, and therefore you refresh the page again.
Here's a good solution for you to work with: https://www.pluralsight.com/guides/work-with-ajax-django
You can do this in Django in a following way:
views.py:
`
def contact(request):
if request.method == "POST":
message_name = request.POST['message-name']
# message-name has to be in your form
# do something with the data in your view
return render(request, 'template.html', {'message_name': message_name})
#return a variable message_name to the context
template.html:
{% if message_name %}
<center><h2><table id="your table"><tr><td></td></tr></h2></center>
{% else %}
<form action="#" method="post">{% csrf_token %}
<div class="row">
<div>
<input type="text" name="message-name">
</div>
<button type="submit">Display table</button>
</form>
{% endif %}
`
You can use input type hidden if you do not want to display any field in the form. The idea is capture the variable from the POST (message-name) and rely on it in the view (message_name)
You may also use localstorage and toggle your display value . Javascript on client side cannot receive post datas , you may store a value on localstorage while submiting the form, once the page is relaoded, check that value stored, modify your display, then reset the value (like you did not submit anything yet again)
example (not sure it works on SO snippet, copy and try it in real)
window.onload = function () {
let mydisplay = localStorage.getItem("myTable");
console.log(mydisplay);
if (mydisplay == "table-cell") {
document.querySelector("#table").style.display = mydisplay;
localStorage.setItem("myTable", "none");
} else {
document.querySelector("#table").style.display = "none";
}
};
function hide() {
document.getElementById("form").submit();
console.log("submit");
localStorage.setItem("myTable", "table-cell");
}
<form action="#" id="form" method="post">
<div style="margin-left: 2rem;">
<!-- <input class="btn btn-primary" type="submit" value="Submit" id="btn" onclick="hide()"> -->
<input class="btn btn-primary" type="button" value="Submit" id="btn" onclick="hide()">
</div>
</form>
<div style="margin-top: 4rem; display: flex; justify-content: center; align-content: center;">
<table id="table">
<tbody>
<tr>
<th scope="row">Profile No. : </th>
<td>{{ProfileNo}}</td>
</tr>
<tr>
<th scope="row">Name : </th>
<td>{{Name}}</td>
</tr>
</tbody>
</table>
</div>
here is a jsfidlle where you can copy/paste the code for a standalone HTML page for testing. https://jsfiddle.net/zb901rLm/

change table header upon selecting of ratio button

I have a page with two radio buttons. One radio button is checked by default but if the other radio button is checked, without pressing a button, I want the header in my table to change.
Here are some snippets:
<table class="table table-sm table-secondary" style="margin-bottom: 0">
<thead style="background-color: #cb5797">
<tr>
<th scope="col" class="text-center">Duration (min)</th>
<th scope="col" class="text-center hideme" data-period="outdoor">
Speed1
</th>
<th scope="col" class="text-center">Incline (%)</th>
</tr>
</thead>
</table>
<div class="btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-secondary active">
<input
type="radio"
name="environment"
id="indoor"
value="indoor"
checked="checked"
/>
Indoor
</label>
<label class="btn btn-secondary">
<input type="radio" name="environment" id="outdoor" value="outdoor" />
Outdoor
</label>
</div>
I have tried to get this example to work but was not successful
Show/hide DIV based on selected with data-toggle="buttons" input radio button bootstrap 3
FYI, I'm new to javascript, therefore please provide plenty of details with your answer.
Every radio button (or checkbox) has an event called onchange. For radiobuttons and checkboxes, the onchange event occurs when the checked state has been changed. You can create two functions and add them as in the snippet below.
Since your table header has the data-period="outdoor" attribute, I'm guessing this is what you want to change. This can be done using the getElementById and setAttribute functions. I also added a bit of code to change the header background-color, for learning purposes.
function toggleIndoor() {
console.log("toggleIndoor changed!");
// Change the header data-period attribute
var headerCell = document.getElementById("tochange");
headerCell.setAttribute("data-period", "indoor");
printHeaderDataPeriod();
// Change the header color
var tableHeader = document.getElementById("table-head");
tableHeader.style.backgroundColor = "#cb5797";
}
function toggleOutdoor() {
console.log("toggleOutdoor changed!");
var headerCell = document.getElementById("tochange");
headerCell.setAttribute("data-period", "outdoor");
printHeaderDataPeriod();
// Change the header color
var tableHeader = document.getElementById("table-head");
tableHeader.style.backgroundColor = "#aa00bb";
}
function printHeaderDataPeriod() {
var headerCell = document.getElementById("tochange");
var headerAttr = headerCell.getAttribute("data-period");
console.log("Table has data-period: " + headerAttr);
}
<div class="btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-secondary active">
<input type="radio" name="environment" id="indoor" value="indoor" checked="checked" onchange="toggleIndoor()"> Indoor
</label>
<label class="btn btn-secondary">
<input type="radio" name="environment" id="outdoor" value="outdoor" onchange="toggleOutdoor()"> Outdoor
</label>
</div>
<table class="table table-sm table-secondary" style="margin-bottom: 0">
<thead style="background-color: #cb5797" id="table-head">
<tr>
<th scope="col" class="text-center">Duration (min)</th>
<th scope="col" class="text-center hideme" data-period="outdoor" id="tochange">Speed1</th>
<th scope="col" class="text-center">Incline (%)</th>
</tr>
</thead>
</table>
If you want to change the header style (color, size etc.), it can be easily done using the setAttribute function or doing element.style.<css-property-name> = <value>, once you got your element by class or by id. Stack overflow has thousands of question like this, about triggering or changing element properties using java-script.
Cheers!

Angular2 Javascript Push - Add item to array

I'm building a form in Angular2 which contains a field that is an array of objects. I've so far built the table with a Delete Row button per row and an Add Row button. These use the JavaScript push() and slice() methods.
There is a big bug though:
When adding a new row, the content of the previous rows is deleted.
That is to say, the content of the row is deleted, not the row itself.
Any ideas why?
Component Code:
public addRow(): void {
this.table.push({});
}
public deleteRow(row: object): void {
this.table.splice(this.table.indexOf(row), 1);
}
HTML Template
<form #TimesheetForm="ngForm" (ngSubmit)="saveTimesheet()">
<div class="row">
<div class="col text-right">
<button type="button" class="btn" (click)="addRow()"><i class="fa fa-plus-square" aria-hidden="true"></i> Add Row</button>
</div>
</div>
<table class="table">
<thead>
<td class="table__header">Date</td>
<td class="table__header">Time</td>
<td class="table__header">Actions</td>
</thead>
<tbody>
<tr *ngFor="let row of table">
<td class="table__item">
<input class="input" [(ngModel)]="row.date" name="date">
</td>
<td class="table__item">
<input class="input" [(ngModel)]="row.time" name="time">
</td>
<td class="table__item">
<button type="button" class="btn btn--negative" (click)="deleteRow(row)"><i class="fa fa-times" aria-hidden="true"></i> Delete</button>
</td>
</tr>
<tr *ngIf="school.rows.length == 0">
<td colspan="3">No rows exist yet. Click Add Row to start logging your timesheet.</td>
</tr>
</tbody>
</table>
</div>
<div class="row">
<div class="col">
<button class="btn btn--positive" type="submit"><i aria-hidden="true" class="fa fa-check"></i> Save</button>
</div>
<div class="col text-right">
<button class="btn btn--negative"><i aria-hidden="true" class="fa fa-times"></i> Cancel</button>
</div>
</div>
</form>
With template driven forms, we need to remember that the name attribute needs to be unique, otherwise the fields will be evaluated as the same field. So what your form does now, is not adding new form controls when you add new rows, instead it manipulates the one and same form field. If you were to put something like <pre>{{TimesheetForm.value | json}}</pre> in your template, you can see, that despite pushing new rows, there is only one form control name date and one form control named time.
So what we need to do is to provide an unique name, we can do that by using the index of the items in your table array. So do the following:
<tr *ngFor="let row of table; let i = index">
<td>
<input [(ngModel)]="row.date" name="date{{i}}">
</td>
<td>
<input [(ngModel)]="row.time" name="time{{i}}">
</td>
<!-- more code here -->
</tr>

Populate dropdown value inside ng-repeat

I am facing an issue with my Angular code, while populating the dropdown inside a HTML table (Code given below).
Could you please help me with what should be done inside modify() to populate the dropdown ?
HTML Code:
<table class="table" ng-app="empApp" ng-controller="employeeController">
<thead>
<tr class="info">
<th>Emp Name</th>
<th>Status</th>
<th colspan="2"> </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="emp in employees">
<td>
<div ng-hide="editingData[emp.id]">{{ emp.name }}</div>
<div ng-show="editingData[emp.id]"><input type="text" ng-model="emp.name" /></div>
</div>
</td>
<td>
<div ng-hide="editingData[emp.id]">{{ emp.status.name }}</div>
<select ng-show="editingData[emp.id]" class="form-control" ng-model="emp.status"
ng-options="status.id as status.name for status in statuses"></select>
</td>
<td colspan="2">
<div class="btn-group">
<button type="submit" class="btn btn-primary" ng-hide="editingData[employee.id]" ng-click="modify(emp)">Modify</button>
<button type="submit" class="btn btn-primary" ng-show="editingData[employee.id]" ng-click="update(emp)">Update</button>
</div>
</td>
</tr>
</tbody>
</table>
Javascript Code:
var empApp = angular.module("empApp", []);
empApp.controller('employeeController', function($scope, $http) {
$scope.statuses = [{"id":1,"name":"Active"}, {"id":1,"name":"Inactive"}];
$scope.employees = [{"id":1,"name":"Mark","status":{"id":1,"name":"Active"}},{"id":2,"name":"Sara","status":{"id":2,"name":"Inactive"}}];
$scope.editingData = {};
for (var i = 0, length = $scope.employees.length; i < length; i++) {
$scope.editingData[$scope.employees[i].id] = false;
}
$scope.modify = function(employee){
$scope.editingData[employee.id] = true;
//Set Employee Status correctly here to populate the dropdown
};
});
My problem is I am NOT able to populate the dropdown with the existing value, as show in the diagram below:
I made this plunker, check if it's what you need.
1: Both status are with id 1. Change them
From:
$scope.statuses = [{"id":1,"name":"Active"}, {"id":1,"name":"Inactive"}];
To:
$scope.statuses = [{"id":1,"name":"Active"}, {"id":2,"name":"Inactive"}];
2:Change your select ng-model to emp.status.id.
From:
<select ng-show="editingData[emp.id]" class="form-control" ng-model="emp.status"
ng-options="status.id as status.name for status in statuses"></select>
To:
<select ng-show="editingData[emp.id]" class="form-control" ng-model="emp.status.id"
ng-options="status.id as status.name for status in statuses"></select>
3: Change your buttons ng-hide/ng-show
From:
<div class="btn-group">
<button type="submit" class="btn btn-primary" ng-hide="editingData[employee.id]" ng-click="modify(emp)">Modify</button>
<button type="submit" class="btn btn-primary" ng-show="editingData[employee.id]" ng-click="update(emp)">Update</button>
</div>
To:
<div class="btn-group">
<button type="submit" class="btn btn-primary" ng-hide="editingData[emp.id]" ng-click="modify(emp)">Modify</button>
<button type="submit" class="btn btn-primary" ng-show="editingData[emp.id]" ng-click="update(emp)">Update</button>
</div>
Update:
As #Rajesh said below you can store the status_id instead of entire status object. Check his fiddle.
Just replace your select tag part with this code
<select ng-show="editingData[emp.id]" class="form-control" ng-model="emp.status"
ng-options="status as status.name for status in statuses track by status.id"></select>
This is because in ng-model you are passing the full object and you need the full object to be tracked by ID in order to fill the dropdown and relevant dropdown value to be selected
Also in your buttons:
<div class="btn-group">
<button type="submit" class="btn btn-primary" ng-hide="editingData[emp.id]" ng-click="modify(emp)">Modify</button>
<button type="submit" class="btn btn-primary" ng-show="editingData[emp.id]" ng-click="update(emp)">Update</button>
</div>
Because you are referencing it by 'emp' and not 'employee' inside ng-repeat as it will be dynamic
You are looping through
<tr ng-repeat="emp in employees">
But in the select list, you are toggling based on:
editingData[employee.id]
Try changing that to
editingData[emp.id]
use emp.id in your button and also in your modify function and loop
use $scope.employees[i].isVisible = false and ng-hide = $scope.employees.isVisible ng-show = $scope.employees.isVisible

Angularjs selecting row of values and populating in a calling page

In my html I have code which dynamically adds rows when a button is clicked and on each row there is a button called "Add"
<form name="{{form.name}}"
ng-repeat="form in forms">
<div ng-repeat="cont in form.contacts">
Add
<input type="text" class="xdTextBox" ng-model="cont.ac"/>
<input type="text" class="xdTextBox" ng-model="cont.a_number"/>
</div>
<button ng-click="submit(form)">Submit</button>
<button ng-click="addFields(form)">Add</button>
<hr>
</form>
Than on my second page /edit i have following code that lists rows of values fetched.
<table>
<tbody ng-repeat="item in alllis">
<tr>
<td>
Select
</td>
<td>
<input type="text" ng-model="item.ac" />
</td>
<td>
<input ng-model="item.a_number />
</td>
</tr>
</tbody>
</table>
What I am trying to figure out is when I am on /edit and I select any row how do i populate back that row data on main page.
Please let me know from /edit page how do i go back to main page populating that row where Add button was clicked. Thanks
Here is the plunker for the first (Main) page.
http://plnkr.co/edit/VVUx2roDTrM9ob2uyZMv?p=preview

Categories

Resources