Angular 4-Add rows in table - javascript

I have this service subscribtion
callSearchService($event) {
this.searchService.searchUser(this.firstName,this.lastName).subscribe(
data => {
console.log("we got: ", data);
this.isNull(data.firstName,data.lastName);
},
error => {
console.log("Error",error);
},
);
and also I have a table .
<thead>
<tr>
<th>#</th>
<th>FirstName</th>
<th>LastName</th>
</tr>
</thead>
I am interested how to add rows dynamically to my table, when i get user info (firstname and lastname) from the callSearchService

something like this
users = []; //user array
<thead>
<tr>
<th>#</th>
<th>FirstName</th>
<th>LastName</th>
</tr>
</thead>
<tbody>
<ng-container *ngFor="let user of users; let i=index;">
<tr>
<th>{{i}}</th>
<td>{{user.firstName}}</td>
<td>{{user.lastName}}</td>
</tr>
</ng-container>
</tbody>
when you receive new user just update array and remaining things will work fine
callSearchService($event) {
this.searchService.searchUser(this.firstName,this.lastName).subscribe(
data => {
console.log("we got: ", data);
this.isNull(data.firstName,data.lastName);
this.users.push(data);
},
error => {
console.log("Error",error);
},
);

You can use ngFor.
suppose you are getting the results in userdetails[] variable.
<tr *ngFor="let userdetail of userdetails | async">
<td>
{{userdetail.firstName}}
</td>
<td>
{{userdetail.lastName}}
</td>
</tr>

Related

Appending a table row from body tag to another table after updating elements within the row

I was told it is good practice to never use HTML tags in JavaScript. So I'm trying my very best to execute the following, but I'm not getting what I want.
I have 2 tables:
Table #1: a table I use to append rows to.
Table #2: a hidden table that has only 1 row, I use that row to change its content and append it to Table #1
Table #1
<table id="myTable">
<thead>
<tr>
<th>Full Name</th>
<th>ID</th>
<th>Email</th>
<th>Phone Number</th>
<th>Job Title</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Table #2
<table id='hiddenTable'>
<tbody>
<tr>
<td><span id="fname"></span></td>
<td><span id="id"></span></td>
<td><span id="email"></span></td>
<td><span id="pnumber"></span></td>
<td><span id="job"></span></td>
</tr>
</tbody>
</table>
Append Function
function addRow(data){
$('#fname').text(data.fname);
$('#id').text(data.id);
$('#email').text(data.email);
$('#pnumber').text(data.pnumber);
$('#job').text(data.job);
var row = $('#hiddenTable').children('tbody').children('tr:first').clone();
$('#myTable > tbody:last-child').append(row);
}
All the snaps are updated everytime addRow() is executed, but when retrieving the row element from the hidden table, it remains empty, unchanged.
please explain why is this happening? and help me make this work without using html tags in javascript and without using the insert row function.
As suggested by #CBroe; the main issue is duplicate ids getting assigned to DOM element. To overcome that first change hidden table's HTML a bit to have class instead of id. Please have a look at below snippet:
function addRow(data) {
//first clone the row from hidden table
var row = $('#hiddenTable').children('tbody').children('tr:first').clone();
//find the span having unique class assigned to them and then set the value
row.find('.fname').text(data.fname);
row.find('.id').text(data.id);
row.find('.email').text(data.email);
row.find('.pnumber').text(data.pnumber);
row.find('.job').text(data.job);
//append the newly formed row to main table
$('#myTable tbody').append(row);
}
$(function() {
var data1 = {
fname: "some name",
id: "some id",
email: "some#email.com",
pnumber: "1212121212",
job: "some job"
};
addRow(data1);
var data2 = {
fname: "some name 22",
id: "some id 22",
email: "some22#email.com",
pnumber: "88888888888888",
job: "some job 22"
};
addRow(data2);
});
#hiddenTable {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<table id="myTable">
<thead>
<tr>
<th>Full Name</th>
<th>ID</th>
<th>Email</th>
<th>Phone Number</th>
<th>Job Title</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<table id='hiddenTable'>
<tbody>
<tr>
<td><span class="fname">aaaaaa</span>
</td>
<td><span class="id"></span>
</td>
<td><span class="email"></span>
</td>
<td><span class="pnumber"></span>
</td>
<td><span class="job"></span>
</td>
</tr>
</tbody>
</table>
All you have done is correct and should work as you expected unless your data object's incorrect. Make a console of your data object and try to figure out how you can extract property from that.
function addRow(data) {
$('#fname').text(data.fname);
$('#id').text(data.id);
$('#email').text(data.email);
$('#pnumber').text(data.pnumber);
$('#job').text(data.job);
var row = $('#hiddenTable tr').first().clone();
$('#myTable tbody').append(row);
}
var data = {
fname: 'first name',
id: '12121',
email: 'email#gmail.com',
pnumber: '111111111',
job: 'my job'
}
addRow(data);
#hiddenTable {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable">
<thead>
<tr>
<th>Full Name</th>
<th>ID</th>
<th>Email</th>
<th>Phone Number</th>
<th>Job Title</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<table id='hiddenTable'>
<tbody>
<tr>
<td><span id="fname"></span>
</td>
<td><span id="id"></span>
</td>
<td><span id="email"></span>
</td>
<td><span id="pnumber"></span>
</td>
<td><span id="job"></span>
</td>
</tr>
</tbody>
</table>
Try this JSFiddle solution.
I change something on addRow function:
function addRow(data){
$('#hiddenTable #fname').text(data.fname);
$('#hiddenTable #id').text(data.id);
$('#hiddenTable #email').text(data.email);
$('#hiddenTable #pnumber').text(data.pnumber);
$('#hiddenTable #job').text(data.job);
var row = $('#hiddenTable tbody').html();
$('#myTable > tbody').append(row);
}

How to iterate over filtered rows in Angular datatable

Lets say, I have simple datatable
<table datatable="" dt-options="dtOptions" dt-column-defs="dtColumnDefs" class="row-border hover">
<thead>
<th>ID</th>
<th>Name</th>
</thead>
<tbody>
<tr ng-repeat"reservation in reservations">
<td>{{reservation.ID}}</td><td>{{reservation.name}}</td>
</tr>
</tbody>
</table>
When I put some string into search box datatable is being filtered. Now I want to iterate in Angular over filtered rows and read IDs to array. How to deal with it in Angular? I can use jquery but I do not want make a mess in code.
$scope.addressDTInstance = {};
var j = $scope.addressDTInstance.DataTable.rows();
<table id="addressSelectionTable" class="table table-condensed table-bordered" datatable="ng" dt-options="addressdtOptions" dt-column-defs="addressdtColumnDefs" dt-instance="addressDTInstance">
This is something to get you on your way. Need an instance of dtInstance which you don't have. So add dt-instance='dtInstance' in the html table tag.
Then initiate it at the top of your controller, $scope.dtInstance = {};.
Perform a click or some action in your javascript that you can set a break point on and then examine your $scope.dtInstance to see what all properties and methods you have. As you see in my snippet I'm accessing DataTable.Rows of my dtInstance. If you need better example or help let leave me a comment and I'll revise.
UPDATE
Here is a method I found that works. I am ofcourse using the DTOptionsbuilder. This will get called twice, first when it is created and second when i populated the array variable that is populating my table. I just check to see if rows exist and that the first one isn't 'No results'.
$scope.addressdtOptions = DTOptionsBuilder.newOptions()
.withOption('bFilter', false)
.withOption('bInfo', false)
.withOption('paging', false)
.withOption('processing', true)
.withOption('aaSorting', [1, 'asc'])
.withOption('language', { zeroRecords: 'No results' })
.withOption('initComplete', function () {
var rows = $("#addressSelectionTable > tbody > tr");
if (rows.length > 0 && rows[0].innerText !== "No results") {
var x = 3;
}
});
Here i am setting that variable that is ng-repeat for table. You may not be doing it my way, but you should be able to figure it out for your way.
$.when($OfficerService.GetAddressSelections($scope.officer.EntityID, $scope.officer.EntityTypeID, $scope.officer.MemberID)).then(function (result) {
$scope.addresses = result.data;
$scope.$applyAsync();
});
<table id="addressSelectionTable" class="table table-condensed table-bordered" datatable="ng" dt-options="addressdtOptions" dt-column-defs="addressdtColumnDefs" dt-instance="addressDTInstance">
<thead>
<tr>
<th></th>
<th>Type</th>
<th>Address</th>
<th>City</th>
<th>State</th>
<th>Zip</th>
<th>Country</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="a in addresses">
<td class="centerColumn">
<input type="button" class="btn btn-primary" value="Select" ng-click="selectAddress(a.AddressID,a.AddressLocationCode,$event)" />
</td>
<td>
<span ng-if="a.AddressLocationCode == 'E'">Office</span>
<span ng-if="a.AddressLocationCode == 'M'">Member</span>
</td>
<td>
{{a.AddressLine1}}
<span ng-if="a.AddressLine2 != null"><br /> {{a.AddressLine2}}</span>
</td>
<td>{{a.City}}</td>
<td>{{a.StateCode}}</td>
<td>{{a.Zip}}</td>
<td>{{a.CountryCode}}</td>
<td>{{a.AddressID}}</td>
</tr>
</tbody>
</table>
For me it works: $scope.dtInstance.DataTable.rows( { search: 'applied' } ).data()

How to use inline editing in angular Js without any buttons in the rows

I have below table,
<div class="md-dialog-main">
<table class="me-hours-table">
<thead>
<th>Product Type</th>
<th>Product Name</th>
<th>
<select>
<option style="background-color:'#FF0000'">weight</option>
<option style="background-color:'#FF0000'">size</option>
</select>
</th>
<th>Price</th>
<th>Qty</th>
</thead>
<tbody>
<tr ng-repeat="data in variants">
<td>{{data.type}}</td>
<td>{{data.name}}</td>
<td>{{data.size}}</td>
<td>{{data.price}}</td>
<td>{{data.qty}}</td>
</tr>
</tbody>
</table>
</div>
The controlling part which take the data is as below,
$scope.idDetails = function(product){
var ids={
mainId : product.mainId,
childId : product.childId
};
console.log(ids.childId);
commerceService.getVariants(ids.childId).
success(function(data) {
toastr.success('Successfully saved', 'Awsome!', {
closeButton: true
});
$scope.variants=[{
type: "cloth",
name: data[0].name,
size: "10",
price: data[0].price,
qty: "1"
}];
console.log($scope.variants.name);
}).error(function(err) {
toastr.error('Saving detals was not Successful', 'Warning', {
closeButton: true
});
});
}
Everything works fine, but I want to use a Angular Js inline editor to edit the rows in the table. First the user can see the data which I get from the controller, then the user should be able to edit the rows. I have searched through the internet but I found inline editing tables which use button to edit and save. I don't want any buttons in my table rows. I want to bind data with the model. So that at the end I can take the data from the table via the model. Please help
After searching in many areas I found an inline edit that do not need any button to edit. The code is as below,
<div class="md-dialog-main">
<table class="me-hours-table">
<thead>
<th>Product Type</th>
<th>Product Name</th>
<th>
<select ng-model="selection">
<option value="weight">weight</option>
<option value="size">size</option>
</select>
</th>
<th>Price</th>
<th>Qty</th>
</thead>
<tbody>
<tr ng-repeat="data in variants">
<td
inline-edit="data.sku"
inline-edit-callback="skuUpdateHandler(newValue)"
inline-edit-btn-edit=""
inline-edit-on-blur="save"
inline-edit-on-click></td>
<td
ng-model="data.name">{{data.name}}</td>
<td
inline-edit="data.sizeOrweight"
inline-edit-callback="sizeUpdateHandler(newValue)"
inline-edit-btn-edit=""
inline-edit-on-blur="save"
inline-edit-on-click></td>
<td
inline-edit="data.price"
inline-edit-callback="priceUpdateHandler(newValue)"
inline-edit-btn-edit=""
inline-edit-on-blur="save"
inline-edit-on-click></td>
<td
inline-edit="data.qty"
inline-edit-btn-edit=""
inline-edit-on-blur="save"
inline-edit-on-click></td>
</tr>
<td
inline-edit-callback="qtyUpdateHandler(newValue)"
inline-edit-btn-edit=""
inline-edit-on-blur="save"
inline-edit-on-click></td>
</tr>
</tbody>
</table>
</div>
The controller is as below,
$scope.skuUpdateHandler = function(newValue) {
console.log(newValue);
};
$scope.sizeUpdateHandler = function(newValue) {
console.log(newValue);
};
$scope.priceUpdateHandler = function(newValue) {
console.log(newValue);
};
Please install ng-inline-edit to use this method. Click
https://github.com/tameraydin/ng-inline-edit to install ng-inline-edit

nested ng-repeat with open particular index with respect to repeated data

Every time the toggle is clicked, all payments are getting replaced with new payments. My problem is how to maintain the payments of a particular index of every click and show at respective index. please help me out
here is my html
<tbody data-ng-repeat="invoice in relatedInvoices>
<tr>
<td class="td-bottom-border">
{{invoice.PayableCurrencyCode}} {{invoice.PayablePaidAmount | number: 2}}<br />
<small>
<a data-ng-click="isOpenPayablePayments[$index] = !isOpenPayablePayments[$index]; togglePayablePayments(invoice.PayableInvoiceId)">Paid</a>
</small>
</td>
</tr>
<tr data-ng-show="isOpenPayablePayments[$index]">
<td>
<table>
<thead>
<tr>
<th>Transaction Id</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="payment in payablePayments">
<td>{{payment.TransactionId}}</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
Here is my javascript
var getPayments = function (invoiceId) {
paymentService.getPayments(invoiceId).then(function (paymentsResponse) {
return paymentsResponse.data;
});
};
$scope.togglePayablePayments = function(invoiceId) {
$scope.payablePayments = getPayments(invoiceId);
};
If I understood correctly, you want to have "payablePayments" for every invoice.
This is working: http://plnkr.co/edit/cj3jxZ?p=info
Try something like
// init at beginning
$scope.payablePayments = [];
$scope.togglePayablePayments = function(invoiceId) {
$scope.payablePayments[invoiceId] = getPayments(invoiceId);
};
and then
<tr data-ng-repeat="payment in payablePayments[invoice.PayableInvoiceId]">
Otherwise you overwrite the object for the preceding invoice.

How can I use ng-switch to toggle displaying a nested table with AngularJS?

I'm trying to use ng-switch in AngularJS to expand a row in a table list to show another table (containing more details about that list item) when it's clicked.
However, I'm having trouble displaying the nested table. I've noticed that the problem only happens with nested tables. If I'm using ng-switch to expand a td instead of a table, it works as expected.
Here's a JSFiddle and my code to illustrate the problem: fiddle
The html:
<body ng-app="listAndDetails">
<div>
<table class="table table-bordered" ng-controller="ListAndOneDetailCtrl">
<thead>
<tr>
<th>Name</th>
<th>e-mail</th>
</tr>
</thead>
<tbody ng-repeat="user in users" ng-click="toggleSelected()" ng-switch on="isSelected(user)">
<tr>
<td>{{user.name}}</td>
<td>{{user.email}}</td>
</tr>
<tr ng-switch-when="true" class="light-gray">
<table>
<tr>
<td>Country</td>
<td>Address</td>
<td>Description</td>
</tr>
<tr>
<td>{{user.country}}</td>
<td>{{user.address}}</td>
<td>{{user.desc}}</td>
</tr>
</table>
</tr>
</tbody>
</table>
</div>
<div ng-controller="ListAndManyDetailsCtrl">
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>e-mail</th>
</tr>
</thead>
<tbody ng-repeat="user in users" ng-controller="UserCtrl" ng-click="toggleSelected()" ng-switch on="isSelected()">
<tr>
<td>{{user.name}}</td>
<td>{{user.email}}</td>
</tr>
<tr ng-switch-when="true" class="light-gray">
<td>{{user.country}}</td>
<td>{{user.address}}</td>
<td>{{user.desc}}</td>
</tr>
</tbody>
</table>
</div>
</body>
The javascript:
angular.module('listAndDetails', [])
.value('users', [
{ name:'Damien', email:'damien#domain.com', desc:'Damien details go here...', country:'US', address:'address1'},
{ name:'Alex', email:'alex#domain.com', desc:'Alex details go here...', country:'UK', address:'address2'}
])
.controller('ListAndOneDetailCtrl', function ($scope, users) {
$scope.users = users;
$scope.selectUser = function (user) {
$scope.selectedUser = user;
};
$scope.isSelected = function (user) {
return $scope.selectedUser === user;
};
})
.controller('ListAndManyDetailsCtrl', function ($scope, users) {
$scope.users = users;
})
.controller('UserCtrl', function ($scope) {
$scope.toggleSelected = function () {
$scope.selected = !$scope.selected;
};
$scope.isSelected = function (user) {
return $scope.selected;
};
});
The div on top attempts to show a nested table upon clicking the list item, but nothing happens.
The div at the bottom attempts to show child td items upon clicking the list item and it works exactly as expected.
Does anyone have any idea what the problem is when I'm trying to expand to show a nested table using ng-switch? And how to solve it?
You have a two errors in your code.
First
In controller ListAndOneDetailCtrl on ng-click you don't have a function toggleSelected.
Second
In first table with controller ListAndOneDetailCtrl you don't have tag td in nested table.
See correct code in jsfiddle
angular.module('listAndDetails', [])
.value('users', [
{ name:'Damien', email:'damien#domain.com', desc:'Damien details go here...', country:'US', address:'address1'},
{ name:'Alex', email:'alex#domain.com', desc:'Alex details go here...', country:'UK', address:'address2'}
])
.controller('ListAndOneDetailCtrl', function ($scope, users) {
$scope.users = users;
$scope.selectUser = function (user) {
$scope.selectedUser = user;
};
$scope.isSelected = function (user) {
return $scope.selectedUser === user;
};
})
.controller('ListAndManyDetailsCtrl', function ($scope, users) {
$scope.users = users;
})
.controller('UserCtrl', function ($scope) {
$scope.toggleSelected = function () {
$scope.selected = !$scope.selected;
};
$scope.isSelected = function (user) {
return $scope.selected;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="listAndDetails">
<div>
<table class="table table-bordered" ng-controller="ListAndOneDetailCtrl">
<thead>
<tr>
<th>Name</th>
<th>e-mail</th>
</tr>
</thead>
<tbody ng-repeat="user in users" ng-click="selectUser(user)" ng-switch on="isSelected(user)">
<tr>
<td>{{user.name}}</td>
<td>{{user.email}}</td>
</tr>
<tr ng-switch-when="true" class="light-gray">
<td>
<table>
<tr>
<td>Country</td>
<td>Address</td>
<td>Description</td>
</tr>
<tr>
<td>{{user.country}}</td>
<td>{{user.address}}</td>
<td>{{user.desc}}</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
</div>
<div ng-controller="ListAndManyDetailsCtrl">
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>e-mail</th>
</tr>
</thead>
<tbody ng-repeat="user in users" ng-controller="UserCtrl" ng-click="toggleSelected()" ng-switch on="isSelected()">
<tr>
<td>{{user.name}}</td>
<td>{{user.email}}</td>
</tr>
<tr ng-switch-when="true" class="light-gray">
<td>{{user.country}}</td>
<td>{{user.address}}</td>
<td>{{user.desc}}</td>
</tr>
</tbody>
</table>
</div>
</body>
There were two problems:
you needed a td section enclosing your table;
<tr>
<td>
<table>
<!-- table information -->
</table>
</td>
</tr>
the controller needed some modifications so that the selected user could have a value.
.controller('ListAndOneDetailCtrl', function ($scope, users) {
$scope.users = users;
$scope.toggleSelected = function(user) {
$scope.selectedUser = user;
};
$scope.selectUser = function (user) {
$scope.selectedUser = user;
};
$scope.isSelected = function (user) {
return $scope.selectedUser === user;
};
})
Here's an updated fiddle: https://jsfiddle.net/jp43agsb/2/

Categories

Resources