AngularJS view not updated after model updates - javascript

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."

Related

How to use Jquery Datatable with AngularJs to export table

I am working on angular website where I need to export table's data to pdf.
I want to use jQuery datatables for it as it alse add some more features like paging,searching and sorting, but getting this error "Error: [$injector:unpr]" on browser's console, even I am not sure using ng-table will make it to datatable or not.
I have also tried using jquery plugin pdfmake but it only make signle page pdf and failed if table have larger data.
Please help and TIA.
Html :-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ng-table/1.0.0/ng-table.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/ng-table/1.0.0/ng-table.min.js"></script>
<table id="myYealyGrid" ng-class="myYealyGridClass" class="table table-responsive gridtable" ng-table="yearly_Table">
<thead>
<tr>
<th>Customer Name</th>
<th>Year</th>
<th>Total Amount($)</th>
</tr>
</thead>
<tbody>
<tr ng-show="YearlyReport.length !=0" ng-repeat="reportrow in YearlyReport" ng-init="setTotal(reportrow)">
<td>{{reportrow.CustomerName}}</td>
<td>{{reportrow.Month}}</td>
<td>{{reportrow.TotalAmount}}</td>
</tr>
<tr ng-show="YearlyReport.length ==0">
<td><small class="nodata">No data found.</small></td>
<td></td>
<td></td>
</tr>
</tbody>
<tfoot>
<tr ng-show="YearlyReport.length !=0" class="bg-warning">
<td class="td-font-bold-custm">Total</td>
<td></td>
<td class="td-font-bold-custm">{{gridTotalAmount | number:2}}</td>
</tr>
</tfoot>
</table>
AngularJs:-
var appKitchenOrderReport = angular.module("myKitchenOrderReportApp", ['ngTable']);
appKitchenOrderReport.controller("myKitchenOrderReportCntrl", function ($scope, $window, $timeout, myKitchenOrderReportService, ngTableParams) {
var getData = myKitchenOrderReportService.SearchData($scope.CustomerName, $scope.Year);
getData.then(function (kitchenreportdata) {
var yearlyGridData = kitchenreportdata.data.OrderYearlyReport;
$scope.yearly_Table = new ngTableParams({
page: 1,
count: 10
}, {
total: $scope.yearlyGridData.length,
getData: function ($defer, params) {
$scope.YearlyReport = $scope.yearlyGridData.slice((params.page() - 1) * params.count(), params.page() * params.count());
$defer.resolve($scope.YearlyReport);
}
});
}, function () {
alert('Error in getting data');
});
});
appKitchenOrderReport.service("myKitchenOrderReportService", function ($http) {
this.getKitchenOrderReportData = function () {
var response = '';
return $http.get("GetOrderReport"); };
this.SearchData = function (CustomerName, Year)
{
var GetParams = new Object();
GetParams.CustomerName = CustomerName;
GetParams.Year = Year
var response = $http({
method: "post",
url: "GetOrderReport",
data: '{model: ' + JSON.stringify(GetParams) + '}',
});
return response;
}
});
you can Use $('#myYealyGrid').DataTable(); to initialize your datatable .
But Use just befor , when you Put data into the HTML table .
It will automatically initialize your Datatable.
Try it and let me know is it working or not .

Dynamic table with JSON data and sticky collapsible rows

I'm using Angular 1 with a factory that polls a REST API for JSON data. This JSON then populates a table with ng-repeat-start, and using ng-repeat-end I have a hidden table row with additional data.
Seems rather ordinary to me.
But the problem is, when I poll the API every 5 or 10 seconds, how can I keep the collapsible table row open when the next poll occurs?
In most cases the data does not change, so there's no reason to close the collapsible row, yet it closes at every poll that my factory makes.
Here's an example of one of the tables.
<table class="pure-table pure-table-horizontal alerts-table" id="alert-nagios-host-table">
<thead>
<tr>
<th>Hostname</th>
<th>Status</th>
<th>Output</th>
</tr>
</thead>
<tbody>
<tr class="parent-row" ng-repeat-start="alert in alerts" ng-click="child.expanded = !child.expanded">
<td>{{alert.hostname}}</td>
<td ng-class="{3:'grayBg', 2:'redBg', 1:'yellowBg', 0:'greenBg'}[alert.state]">{{alert.status}}</td>
<td>{{alert.output}}</td>
</tr>
<tr class="child-row" ng-init="child.expanded = false" ng-show="child.expanded" ng-repeat-end>
<td colspan=4>Duration: {{alert.duration}}</td>
</tr>
</tbody>
</table>
Here is my factory that polls the data, and an example of one of the angular controllers.
mondashApp.factory('AlertsPoller', function ($http, $timeout) {
var data = {resp: {}, count: 0};
var count=0;
var poller = function (url, success) {
count++;
$http.get(url).then(function (responseData) {
data.count = count;
data.resp = responseData.data;
success(data);
$timeout(function () {poller(url, success);}, 5000);
});
};
return {
poller: poller
};
});
mondashApp.controller('nagiosHostAlertsCtrl', function nagiosHostAlertsCtrl($scope, AlertsPoller) {
AlertsPoller.poller('/alert/nagios/host', function(response) {
$scope.alerts = response.resp.alerts;
});
});

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

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.

Generating table from json in AngularJS

I'm trying to generate HTML table from json in AngularJS.
I receive JSON in format like this:
My Service for getting the data looks like this :
customAPI.getUsers = function() {
return $http({
method: 'JSONP',
url: 'http://arka.foi.hr/WebDiP/2013_projekti/WebDiP2013_069/api/admin/users.php'
});
};
and controller for that code looks like this
controller('usersController', function($scope, customAPIservice) {
$scope.filterName = null;
$scope.usersList = [];
/*Search*/
$scope.searchFilter = function(user) {
var keyword = new RegExp($scope.filterName, 'i');
return !$scope.filterName || keyword.test(user.korisnici.korisnik_ime) || keyword.test(user.korisnici.korisnik_prezime);
};
customAPIservice.getUsers().success(function(response) {
$scope.usersList = response.korisnici;
});
});
and my view looks like this :
<input type="text" ng-model="nameFilter" placeholder="Trazi..."/>
<h2 >Korisnici</h2>
<table>
<thead>
<tr>
<th colspan="6">Korisnici sustava</th>
</tr>
<th>Surname</th>
</thead>
<tbody>
<tr ng-repeat="user in usersList| filter: searchFilter">
<td>{{$index + 1}}</td>
<td>{{user.korisnik.korisnik_prezime}}</td>
<td>{{user.korisnik.korisnik_username}}</td>
</tr>
<tr ng-show="usersList == ''">
<td colspan="5">
<img src="img/ajax-loader.gif" />
</td>
</tr>
</tbody>
</table>
I think I messed up somewhere with binding the data with the view but I' still pretty new with angular so I can't find what is wrong. Also I've looked up over internet and couldn't find anything.Please help.
You are not correctly access the properties in your data. Use:
/*Search*/
$scope.searchFilter = function(user) {
var keyword = new RegExp($scope.filterName, 'i');
return !$scope.filterName || keyword.test(user.korisnik.korisnik_ime) || keyword.test(user.korisnik.korisnik_prezime);
};

Angular, view not updating when changing model

I'm changing a model and I was expecting the view to update but it isn't:
Here is my view:
<div ng-controller="showCarCtrl">
<h1>Damaged Cars</h1>
<table border="1">
<tr>
<th>Plate Number</th>
<th>Brand</th>
<th>Color</th>
</tr>
<tr ng-repeat="car in cars" ng-show="car.damaged">
<td>{{car.plate_number}}</td>
<td>{{car.brand}}</td>
<td>{{car.color}}</td>
<td>
<button ng-click="setRepaired(car.cid)">Repaired</button>
</td>
</tr>
</table>
</div>
Here is the controller:
app.controller('showCarCtrl', function($scope, $rootScope,CarService){
$scope.setDamaged = function(cid){
console.log("setting the car as damaged "+cid)
$rootScope.loading = true;
CarService.setDamageCar(cid)
.then(function(data){
$rootScope.loading = false;
console.log("set damage 1")
for(var i=0; i<$scope.cars.length; i++) {
console.log("setting car as damage");
if ($scope.cars[i]==cid) {
$scope.cars[i].damaged = 1
$scope.$apply();
console.log("it enters here");
break;
}
console.log($scope.cars)
}
},
//deferred
function(data){
console.log('Car Service failed');
$rootScope.loading = false;
});
};
});
I've checked from the server, the reply from the server is properly comming and I'm successfully updating the model at $scope.cars[i].damaged = 1, the only issue is that I was expecting the view to change because as shown above, in the view, I've something as <tr ng-repeat="car in cars" ng-show="car.damaged">, but the view is not updating
I think you have an error in your code here:
if ($scope.cars[i]==cid) {
Maybe it should be like this:
if ($scope.cars[i].cid === cid) {

Categories