Angular - link two API sources in table based on ID FK - javascript

I'm really new to Angular and i'm trying to create a list of user transactions that presents the time of the action and the user's name. In my audit API I have an action ID and the User FK which associates with my User API and i'm displaying it as follows:
HTML
<table>
<thead>
<tr>
<th>
Date/Time
</th>
<th>
User
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="audit in audit.data>
<td>{{audit.audit_date_time}}</td>
<td>**{{audit.audit_user_fk}}**</td> **<--I need the name not the ID here**
</tr>
</tbody>
</table>
My Apis are as follows:
AUDIT
[
{
"audit_id": "1",
"audit_date_time": "2016-01-28 12:46:20",
"audit_user_fk": "97"
}
]
USER
[
{
"user_id": "97",
"user_full_name": "Mr.User",
}
]
Controller, which is working fine GETting the data from each API:
app.controller('auditControl', ['$scope','auditService', 'userService', function ($scope, auditService, userService) {
var auditLogs = auditService.query(function () {
$scope.audit.data = auditLogs;
});
var user = userService.query(function () {
$scope.auditUser = user;
});
}]);
So my main issue i'm having is getting the user name in the table instead of the foreign key value. I've stripped out a lot of this just so we can focus on the main problem. Getting the user name from the user API, based on the FK in the Audit API and repeated based on the items in the Audit API.
Any help greatly appreciated and apologies for the noob question!

Create a custom filter.
app.filter("lookupUser", function() {
function lookup (idNum, userList) {
var userName = "UNKNOWN";
angular.forEach(userList, function(user) {
if ( user.user_id == idNum ) {
userName = user.user_full_name;
};
});
return userName;
};
return lookup;
});
Then in your template:
<tr ng-repeat="audit in audit.data>
<td>{{audit.audit_date_time}}</td>
<td>{{audit.audit_user_fk | lookupUser : auditUser }}</td>
</tr>

You could do something like this:
Controller:
app.controller('auditControl', ['$scope','auditService', 'userService', function ($scope, auditService, userService) {
var auditLogs = auditService.query(function () {
$scope.audit.data = auditLogs;
});
var user = userService.query(function () {
$scope.auditUser = user;
});
$scope.getUserName = function (id) {
var result = $scope.users.filter(function( user ) {
return user.user_id == id;
});
if (angular.isDefined(result) && result.length > 0) {
return result[0].user_full_name;
} else {
return "--";
}
}
}]);
HTML
<table>
<thead>
<tr>
<th>
Date/Time
</th>
<th>
User
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="audit in audit.data">
<td>{{audit.audit_date_time}}</td>
<td>**{{getUserName(audit.audit_user_fk)}}**</td> **<--I need the name not the ID here**
</tr>
</tbody>
</table>
I don't know where the users array are, so I called $scope.users.

Related

Cannot display Users from database in localhost

I'm trying to make a web app in Java that connects to a database and shows a table with users.
I have problem with this piece of code in HTML but I believe that this is only the result of earlier coding.
So the code in curly brackets ( {{user.name}} and other) gets underlined and says "Unresolved variable"
I have no idea where is the problem so I'm pasting my angular methods and Java code where I made a list with users that should be displayed in localhost.
This is the code from github that I tried to rewrite but instead of hotels I'm displaying Users.
https://github.com/dangeabunea/RomanianCoderExamples/blob/master/BookingDemo/src/main/resources/templates/index.html
HTML code:
<!-- Display users in a table -->
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Surname</th>
<th>Login</th>
<th>Is Deleted?</th>
<th style="width: 90px"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="user in vm.users">
<td>{{user.name}}</td>
<td>{{user.surname}}</td>
<td>{{user.login}}</td>
<td>{{user.isDeleted}}</td>
<td>
<button class="btn btn-danger" ng-click="vm.deleteUser(user.id)">Delete</button>
</td>
</tr>
</tbody>
</table>
JavaScript (angular):
angular
.module('app')
.controller('UserController', UserController);
UserController.$inject = ['$http'];
function UsersController($http) {
var vm = this;
vm.users = [];
vm.getAll = getAll;
vm.deleteUser = deleteUser;
init();
function init(){
getAll();
}
function getAll(){
var url = "/users/all";
var usersPromise = $http.get(url);
usersPromise.then(function(response){
vm.users = response.data;
});
}
function deleteUser(id){
var url = "/users/delete/" + id;
$http.post(url).then(function(response){
vm.users = response.data;
});
}
}
Java:
#Component
public class DatabaseSeeder implements CommandLineRunner {
private UserRepository userRepository;
#Autowired
public DatabaseSeeder(UserRepository userRepository){
this.userRepository = userRepository;
}
#Override
public void run(String... strings) throws Exception {
List <Users> users = new ArrayList<>();
users.add(new Users("John", "Kowalski", "john332", false));
users.add(new Users( "Debby", "Ryan", "debbs84", false));
users.add(new Users( "Michael", "Smith", "grizzly98", false));
userRepository.saveAll(users);

How to get SUM of the table field? - Angularjs & Sqlite

I'm trying to get the sum of my table row (amount) with Angularjs which is connected to my sqlite database
I have managed to build CRUD operations perfectly but now I'm stuck on getting the sum of my amount field
Here's part of my html code:
<table id="tableSales" ng-init="listSales()">
<thead class="bz-tablecell">
<tr>
<th id="table-checkbox"><input type="checkbox" onclick="toggle(this);" id="chk-all"></th>
<th><b>Name</b></th>
<th><b>Amount</b></th>
<th><b>Quantity</b></th>
<th><b>Customer</b></th>
<th><b>Date</b></th>
<th class="export-ignore"><b>Status</b></th>
<th class="export-ignore"><b>Actions</b></th>
</tr>
</thead>
<tbody>
<tr class="bz-tablecell" dir-paginate="sale in sales|filter:search|itemsPerPage:20">
<td id="table-checkbox"><input type="checkbox"></td>
<td style="font-weight: 600">{{sale.name}}</td>
<td>{{sale.amount | currency: "TZS "}}</td>
<td>{{sale.quantity}}</td>
<td>{{sale.customer}}</td>
<td>{{sale.date}}</td>
<td class="export-ignore"><span class="approved" style="border-radius: 0 !important;">{{sale.status}}</span></td>
<td class="export-ignore"><a ng-click="delete(sale)">Manage</a></td>
</tr>
<tr ng-if="sales.length <= 0">
<td colspan="8" rowspan="4" class="center empty-state">
<b class="top">There are no sales yet!</b>
<br>Start by adding a new one.
</td>
</tr>
</tbody>
</table>
And here's is my angularjs code which do CRUD operations:
"USE STRICT";
app.controller("salesController", function ($scope, $location, dbService) {
$scope.sub = {
'title': 'Sales Orders'
}
$scope.listSales = function () {
//FETCH
dbService.runAsync("SELECT * FROM sales WHERE active = 1", function (data) {
$scope.sales = data;
});
}
$scope.save = function () {
if ($scope.sale.id) {
//EDIT
var id = $scope.sale.id;
delete $scope.sale.id;
delete $scope.sale.$$hashKey;
dbService.update('sales', $scope.sale, {
id: id
});
} else {
//SAVE
dbService.insert('sales', $scope.sale);
}
$scope.sale = {};
$scope.listSales();
}
$scope.delete = function (data) {
//DELETE
if (confirm("Are you sure you want to delete this sale?")) {
dbService.update('sales', {
active: 0
}, {
id: data.id
});
$scope.listSales();
}
}
});
What I need to do is get all sum of amount field, please help. Thank you
To compute a sum:
$scope.listSales = function () {
//FETCH
dbService.runAsync("SELECT * FROM sales WHERE active = 1", function (data) {
$scope.sales = data;
//COMPUTE Sum
$scope.sum = data.reduce( ( (_,sum) => sum + _.amount) , 0);
});
}
For more information, see
MDN JavaScript Reference - array.reduce

How to automatically load/refresh view data after delete in AngularJS?

I am working on a Web Application using Laravel as backend API and AngularJS for frontend. I have successfully fetched the data from Laravel API and displayed it via AngularJS ng-repeat. Now i want a delete button for each record which is displayed in the table. When a user click that delete button it should delete the clicked record.
I did the following try which is working perfectly.But the problem occurs when i click delete button it deletes record from database but it is not refreshing the records list , instead of refreshing it just shows the headers titles of table and nothing else. When i manually refresh it from browser then it displays back the records list. I want to load the list automatically after the record is deleted.
Console Error : Console Error: DELETE
http://localhost/ngresulty/public/api/result/50?id=50 500 (Internal
Server Error)
Before Delete ( List ):
After delete Scene:
MainCtrl.js
$scope.deleteResult = function(id) {
$scope.loading = true;
Result.destroy(id)
.success(function(data) {
// if successful, we'll need to refresh the comment list
Result.get()
.success(function(data) {
$scope.students = data;
$scope.loading = false;
});
});
};
MyAppService.js
angular.module('myAppService', [])
.factory('Result', function($http) {
return {
get : function() {
return $http.get('api/result');
},
show : function(id) {
return $http.get('api/result/' + id);
},
save : function(resultData) {
return $http({
method: 'POST',
url: 'api/result',
headers: { 'Content-Type' : 'application/x-www-form-urlencoded' },
data: $.param(resultData)
});
},
destroy : function(id) {
return $http.delete('api/result/' + id,{params: {id}});
}
}
});
App.js
var myApp = angular.module('myApp', ['mainCtrl', 'myAppService']);
Results View :
<table class="table table-striped">
<thead>
<tr>
<th>Roll No</th>
<th>Student Name</th>
<th>Father Name</th>
<th>Obtained Marks</th>
<th>Total Marks</th>
<th>Percentage</th>
<th>Delete</th>
</tr>
</thead>
<tbody ng-hide="loading" ng-repeat="student in students | filter:searchText">
<tr>
<td>#{{ student.rollno }}</td>
<td>#{{ student.name }}</td>
<td>#{{ student.fname }}</td>
<td>#{{ student.obtainedmarks }}</td>
<td>#{{ student.totalmarks }}</td>
<td>#{{ student.percentage }}</td>
<td>
Delete</p>
</td>
</tr>
</tbody>
</table>
What I tried but not working :
$scope.deleteResult = function(id) {
$scope.loading = true;
Result.destroy(id)
.success(function(data) {
// do something with data if you want to
$scope.students.splice(id, 1);
});
};
Solution :
Whenever you get 500 internal error the issue will be from server side. The issue was with server side all i did was change my destroy service to
destroy : function(id) {
return $http.delete('api/result/' + id);
}
and in laravel controller i was returning a bool value true but i changed that to ID
return \Response::json($studentid);
because i was in need of that ID for success return and then it worked like a charm.
The problem is Array splice method takes the index of array as first argument and you are providing it Student Id which is not a array index. You have to find the index of student id in the array then pass it into the splice method
$scope.findWithAttr= function(array, attr, value) {
for(var i = 0; i < array.length; i += 1) {
if(array[i][attr] === value) {
return i;
}
} }
Now you can call this function is destroy success block.
$scope.deleteResult = function(idToDelete) {
$scope.loading = true;
$http.delete('api/result/' + id,{params: {id}}); }
.then(function(data) {
var index=$scope.findWithAttr($scope.students,id,idToDelete);
$scope.students.splice(index, 1);
});
};
You are splicing the data incorrectly.
Do like this to splice the data in destroy success block.
var del_index = $scope.students.findIndex(function(d){return d.id == id});
if(del_index>0)//if index of the id to be removed found
$scope.students.splice(del_index, 1);
There is a javascript library called lodash
This library provides the remove function where you can remove an element from the data.
Sometimes slice does not work. SO try this hopefully it would work.
$scope.deleteResult = function(id) {
$scope.loading = true;
Result.destroy(id)
.success(function(data) {
// do something with data if you want to
_.remove($scope.students,function(student){
return id==studednt.id;
}
});
};

AngularJS view not updated after model updates

New to Angular, I am trying to save a form and update the view after calling a PUT or POST call to the backend. Once I receive an OK status from the backend, I am updating my models with the latest response. But only the model in the directive "ng-click" gets updated but others do not. Here is my code:
///HTML
<table class="footable table table-stripped toggle-arrow-tiny" data-page-size="8">
<thead>
<tr>
<th data-toggle="all">Release Title</th>
<th data-hide="all">Release Genre</th>
<th data-hide="all">UID</th>
<th data-hide="all">Classical</th>
<th data-hide="all">Tracks</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="album in vm.albums" footable>
// This one (album.data.title) gets updated but the other ones do not
<td ng-click="vm.editAlbum(album, $index)">{{album.data.title}}</small></td>
<td>{{album.data.genre}}</td>
<td>{{album.data.uid}}</td>
<td ng-if!="album.data.classical">No</td>
<td ng-if="album.data.classical">Yes</td>
<td>
<li ng-repeat="track in album.data.tracks">
<a ng-click="vm.selectTrack(album, track)">{{track.title}}</a>
</li>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5">
<ul class="pagination pull-right"></ul>
</td>
</tr>
</tfoot>
</table>
Here is my controller:
// controller.js (Just pasting the saveRelease method that does the on-click event handling in HTML:
(function (){
angular.module('app.uploadedReleases').controller('UploadedReleasesController', UploadedReleasesController);
UploadedReleasesController.$inject = ['$http', '$log', '$scope', '$state', '$rootScope', 'APP_CONFIG'];
function UploadedReleasesController ($http, $log, $scope, $state, $rootScope, APP_CONFIG){
var vm = this;
vm.albums = []; // list of all albums
vm.albumPriority = [0, 4, 6, 8, 10];
vm.getAlbumTracks = getAlbumTracks;
vm.editAlbum = editAlbum;
vm.selectTrack = selectTrack;
vm.selected = {};
vm.saveRelease = saveRelease;
vm.testingAlbumSelected = false;
return init();
function init(){
$http.get('http://localhost:8080/api/releases').then(function(responseData){
//check the status from the response data.
vm.responseStatus = responseData.status;
if(vm.responseStatus !== 200){
//error message
}
// else, Parse the json data here and display it in the UI
for(var album in responseData.data){
vm.albums.push({slug: album, data: responseData.data[album]});
}
})
}
function getAlbumTracks(slug, index){
$http.get('http://localhost:8080/api/releases/' + slug).success(function(trackResponse){
//parse each album and get the track list
vm.showingAlbumIndex = index;
vm.albums.tracks = [];
vm.selected = {};
vm.selected.album = vm.albums[index];
vm.testingAlbumSelected = true;
for(var i = 0; i<trackResponse.tracks.length; i++) {
vm.albums.tracks.push(trackResponse.tracks[i]);
}
$log.debug(vm.albums.tracks);
vm.formAlbum = new Album(vm.selected.album.data.upc,
vm.selected.album.data.title,
vm.selected.album.data.label,
vm.selected.album.data.genre,
vm.selected.album.data.releaseType,
vm.selected.album.data.holdDate,
vm.selected.album.data.priority,
vm.selected.album.data.memo);
})
}
function selectTrack(album, track){
vm.selected.album = album;
vm.selected.track = track;
vm.testingAlbumSelected = false;
}
function editAlbum(album, index){
getAlbumTracks(album.slug, index);
vm.selected = album;
}
function saveRelease(){
// Call the PUT request to update the release metadata and refresh the page
// so that the Album list gets updated with the latest changes
var url = 'http://localhost:8080/api/releases/' + vm.selected.album.slug;
$http.put(url, vm.formAlbum).then(function(saveAlbumResponse){
if(saveAlbumResponse.status === 202){
//successfully saved response on backend
// Update the current models to show the newer data
vm.album.data = vm.formAlbum;
console.log("album array vm.albums = "+vm.albums);
}
})
}
})();
Any idea why ?
try remove "var vm=this" line. And rename vm.xxxx to $scope.xxxx in your controller.
in the view: remove the "vm."

ng-repeat filter not applied

I have a simple code that pulls some data in intervals and prints into a table. I'd like to filter the table rows but any filters that I'm trying to apply are ignored. What am I missing? This is basically a plain copy from AngularJS docs page.
The only difference here seems to be that I'm using a controller and the example code does not.
Example Plunkr.
HTML template:
<table>
<thead>
<tr>
<th>Pages</th>
<th>Last action</th>
<th>Total time</th>
</tr>
<tr>
<th><input ng-model="search.count"></th>
<th><input ng-model="search.last"></th>
<th><input ng-model="search.time"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in adminCtrl.rows | filter:search ">
<td>{{ row.count }}</td>
<td>{{ row.last }}</td>
<td>{{ row.time }}</td>
</tr>
</tbody>
</table>
Controller:
(function(){
var app = angular.module('admin', []);
app.controller('AdminController', ['$interval', '$http', function($interval, $http){
var admin = this;
admin.rows = [];
var timer = undefined;
function updateRows() {
$http.get('test.json').success(function(data) {
admin.rows = data;
});
}
admin.stopTimer = function() {
if (angular.isDefined(timer)) {
$interval.cancel(timer);
timer = undefined;
}
};
admin.startTimer = function(delay) {
if (!angular.isDefined(delay)) {
// Default interval 10 seconds.
delay = 10000;
}
if (!angular.isDefined(timer)) {
timer = $interval(updateRows, delay);
}
};
admin.isTimerRunning = function() {
return angular.isDefined(timer);
}
// Initialize rows.
updateRows();
// Start the interval timer.
admin.startTimer();
}]);
})();
the filter is only apply in array where your data is an object. simply convert the data to array should work. if you happend to use lo-dash, that's a easy job to do :
function updateRows() {
$http.get('test.json').success(function(data) {
admin.rows = _.toArray(data);
});
}
It's because your ng-repeat is repeating over an object and not an array, here is your adminCtrl.rows:
{"a":{"count":14,"last":"Lorem ipsum","time":45},"b":{"count":5,"last":"Some title","time":13}}
Make it an array:
[{"count":14,"last":"Lorem ipsum","time":45},{"count":5,"last":"Some title","time":13}}]
If you want to use filter over an object, you'll have to roll your own using a
.filter("MY_FILTER", function(){
...
});

Categories