Displaying data using AngularJS - angularjs

I am trying to represent some data taken from database in a table. I am using jersey as back-end and I have tested it in Postman that it works. The problem is I cannot display my data in the table in front-end, when I use AngularJS. It only shows me a blank table, without data at all. I am pretty new to AngularJS and I really want anyone of you to help me find the problem with my piece of code below.
list_main.js
angular.module('app', [])
.controller('ctrl', function($scope, $http){
$scope.bookList = [];
$scope.loadData = function(){
$http.get('http://localhost:8080/BookCommerce/webapi/list').then(function(data){
$scope.bookList = data;
console.log($scope.bookList);
})
}
$scope.loadData();
})
index2.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>List Of Books</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></s‌​cript>
<script src="js/list_main.js"></script>
</head>
<body>
<div class="row" data-ng-controller="ctrl" data-ng-app="app" data-ng-init="loadData()" style="margin: 10px;">
<div class="col-md-7">
<div class="panel panel-primary">
<table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered" id="exampleone">
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Author</th>
<th>Description</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="book in bookList">
<td>{{book.book_id}}</td>
<td>{{book.book_title}}</td>
<td>{{book.book_author}}</td>
<td>{{book.book_description}}</td>
<td>{{book.book_price}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
ListDAO.java
public class ListDAO {
public List<Book> findAll() {
List<Book> list = new ArrayList<Book>();
Connection c = null;
String sql = "SELECT * FROM book";
try {
c = ConnectionHelper.getConnection();
Statement s = c.createStatement();
ResultSet rs = s.executeQuery(sql);
while (rs.next()) {
list.add(processRow(rs));
}
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
ConnectionHelper.close(c);
}
return list;
}
protected Book processRow(ResultSet rs) throws SQLException {
Book book = new Book();
book.setBook_id(rs.getInt("book_id"));
book.setBook_title(rs.getString("book_title"));
book.setBook_author(rs.getString("book_author"));
book.setBook_description(rs.getString("book_description"));
book.setBook_price(rs.getInt("book_price"));
return book;
}
}
ListResource.java
#Path("/list")
public class ListResource {
ListDAO dao=new ListDAO();
#GET
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public List<Book> findAll() {
System.out.println("findAll");
return dao.findAll();
}
}
Please help me. Thank you!

Okay this is much better than the last time,
There's still some bits wrong with your JS - it should look like this :
// Code goes here
var baseUrl = "https://demo5019544.mockable.io/";
angular.module('app', [])
.controller('ctrl', function($scope, $http){
$scope.bookList = [];
$scope.loadData = function(){
$http.get(baseUrl + 'BookCommerce/webapi/list').then(function(data){
$scope.bookList = data.data;
})
}
})
I made a demo REST service at : https://demo5019544.mockable.io/BookCommerce/webapi/list
which produces the kind of output your web service should product, I tested the code with this web service and with the tweaks I made it worked -- Yay.
The last thing I'd do now is check that your web service is throwing out the same / similar output that my mock is producing.

Related

Unexpected End of Expression when used with #Html.Raw(Model)

I am trying to use AngularJs with ASP.NET MVC - this is my first attempt.
Index.html
#model string
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container" ng-init="courses = [{'name':'first'},{'name':'second'},{'name':'third'}]">
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="course in courses">
<td>{{ course.name }}</td>
</tr>
</tbody>
</table>
_Layout.cshtml
<!DOCTYPE html>
<html ng-app>
<head>
<meta name="viewport" content="width=device-width" />
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<script src="~/Scripts/angular.min.js"></script>
<title></title>
</head>
<body>
#RenderBody()
</body>
</html>
Above works fine and grid is displayed with Name as header and first, second and third as 3 rows. So my next step is to use
courses = #Html.Raw(Json.Encode(Model))
instead of
courses = [{'name':'first'},{'name':'second'},{'name':'third'}]
CourseController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace AngularJsMvc.Controllers
{
public class CoursesController : Controller
{
// GET: Courses
public ActionResult Index()
{
return View("Index", "", "[{'name':'first'},{'name':'second'}, {'name':'third'}]"); //This works fine when used with #Html.Raw(Model) in index.html
//return View("Index", "", GetCourses()); //This doesn't work when used with with #Html.Raw(Model) in index.html
}
public string GetCourses()
{
var courses = new[]
{
new Course { Name = "First" },
new Course { Name = "Second" },
new Course { Name = "Third" }
};
var settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
return JsonConvert.SerializeObject(courses, Formatting.None, settings);
}
}
public class Course
{
public string Name { get; set; }
}
}
This works fine if I use
return View("Index", "", "[{'name':'first'},{'name':'second'},{'name':'third'}]");
But if I use
return View("Index", "", GetCourses());
Then, below is the error I get. Please help - I have been struggling for almost entire day yesterday. I tried with or without Json.Encode
angular.min.js:123 Error: [$parse:ueoe]
http://errors.angularjs.org/1.6.4/$parse/ueoe?p0=courses%20%3D
at angular.min.js:6
"<div class="container" ng-init="courses = " [{\"name\":\"first\"},{\"name\":\"second\"},{\"name\":\"third\"}]""="">"
The following worked for me:
<div class="container" ng-init="courses = #Newtonsoft.Json.JsonConvert.DeserializeObject(Model)">
This also works:
<div class="container" ng-init="courses = #HttpUtility.HtmlDecode(Model)">
It's all about how angular treats the object it tries to parse and since you're passing an HTML decoded string it will treat as a string and therefore it won't be able to iterate threw it.

Filtering ng-repeat result set is not working

I tried to create a textbox based filtering of a ng-repeat result. Though there is no errors listed, the filtering is not working. What is missing here?
Updated code after making following change:
<tbody ng-repeat="objReview in reviewsList | myCustomFilter:criteria" >
The filter is gettiing called two times for each row. How to make it call only once?
Code
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular-resource.js"></script>
<style type="text/CSS">
table
{border-collapse: collapse;width: 100%;}
th, td
{text-align: left;padding: 8px;}
tr:nth-child(even)
{background-color: #f2f2f2;}
th
{background-color: #4CAF50;color: white;}
</style>
<script type="text/javascript">
//defining module
var app = angular.module('myApp', ['ngResource']);
//defining factory
app.factory('reviewsFactory', function ($resource) {
return $resource('https://api.mlab.com/api/1/databases/humanresource/collections/Reviews',
{ apiKey: 'myKey' }
);
});
//defining controller
app.controller('myController', function ($scope, reviewsFactory)
{
$scope.criteria = "";
$scope.reviewsList = reviewsFactory.query();
});
app.filter('myCustomFilter', function ()
{
return function (input, criteria)
{
var output = [];
if (!criteria || criteria==="")
{
output = input;
}
else
{
angular.forEach(input, function (item)
{
alert(item.name);
//alert(item.name.indexOf(criteria));
//If name starts with the criteria
if (item.name.indexOf(criteria) == 0)
{
output.push(item)
}
});
}
return output;
}
});
</script>
</head>
<body ng-app="myApp">
<div ng-controller="myController">
<label>
SEARCH FOR: <input type="text" ng-model="criteria">
</label>
<table>
<thead>
<tr>
<th>Name</th>
<th>Review Date</th>
</tr>
</thead>
<tbody ng-repeat="objReview in reviewsList | myCustomFilter:criteria" >
<tr>
<td>{{objReview.name}}</td>
<td>{{objReview.createdOnDate}}</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Further Reading
Is this normal for AngularJs filtering
How does data binding work in AngularJS?
As noted in the comments by Lex you just need to get rid of the prefix 'filter', so change
<tbody ng-repeat="objReview in reviewsList | filter:myCustomFilter:criteria" >
to
<tbody ng-repeat="objReview in reviewsList | myCustomFilter:criteria" >
In addition you should set an initial value for your controller's property criteria as otherwise your initial list will be empty as your filter will not match anything due to the comparison operator === which takes the operands' types into account and critiera will be undefined until you first enter something in your textbox.
app.controller('myController', function ($scope, reviewsFactory)
{
$scope.criteria = '';
$scope.reviewsList = reviewsFactory.data();
});

AngularJS ng-click not firing controller method

I'm sure everyone has seen questions of a similar ilk, and trust me when I say I have read all of them in trying to find an answer. But alas without success. So here goes.
With the below code, why can I not get an alert?
I have an ASP.Net MVC4 Web API application with AngularJS thrown in. I have pared down the code as much as I can.
I know that my AngularJS setup is working correctly because on loading my view it correctly gets (via a Web API call) and displays data from the database into a table (the GetAllRisks function). Given that the Edit button is within the controller, I shouldn't have any scope issues.
NB: the dir-paginate directive and controls are taken from Michael Bromley's excellent post here.
I would appreciate any thoughts as my day has degenerated into banging my head against my desk.
Thanks,
Ash
module.js
var app = angular.module("OpenBoxExtraModule", ["angularUtils.directives.dirPagination"]);
service.js
app.service('OpenBoxExtraService', function ($http) {
//Get All Risks
this.getAllRisks = function () {
return $http.get("/api/RiskApi");
}});
controller.js
app.controller("RiskController", function ($scope, OpenBoxExtraService) {
//On load
GetAllRisks();
function GetAllRisks() {
var promiseGet = OpenBoxExtraService.getAllRisks();
promiseGet.then(function (pl) { $scope.Risks = pl.data },
function (errorPl) {
$log.error("Some error in getting risks.", errorPl);
});
}
$scope.ash = function () {
alert("Bananarama!");}
});
Index.cshtml
#{
Layout = null;
}
<!DOCTYPE html>
<html ng-app="OpenBoxExtraModule">
<head>
<title>Risks</title>
<link href="~/Content/bootstrap.min.css" rel="stylesheet">
<script type="text/javascript" src="~/Scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="~/Scripts/bootstrap.min.js"></script>
<script type="text/javascript" src="~/Scripts/angular.js"></script>
<script type="text/javascript" src="~/Scripts/AngularJS/Pagination/dirPagination.js"></script>
<script type="text/javascript" src="~/Scripts/AngularJS/module.js"></script>
<script type="text/javascript" src="~/Scripts/AngularJS/service.js"></script>
<script type="text/javascript" src="~/Scripts/AngularJS/controller.js"></script>
</head>
<body>
<div ng-controller="RiskController">
<table>
<thead>
<tr>
<th>Risk ID</th>
<th>i3_n_omr</th>
<th>i3_n_2_uwdata_key</th>
<th>Risk Reference</th>
<th>Pure Facultative</th>
<th>Timestamp</th>
<th></th>
</tr>
</thead>
<tbody>
<tr dir-paginate="risk in Risks | itemsPerPage: 15">
<td><span>{{risk.RiskID}}</span></td>
<td><span>{{risk.i3_n_omr}}</span></td>
<td><span>{{risk.i3_n_2_uwdata_key}}</span></td>
<td><span>{{risk.RiskReference}}</span></td>
<td><span>{{risk.PureFacultative}}</span></td>
<td><span>{{risk.TimestampColumn}}</span></td>
<td><input type="button" id="Edit" value="Edit" ng-click="ash()"/></td>
</tr>
</tbody>
</table>
<div>
<div>
<dir-pagination-controls boundary-links="true" template-url="~/Scripts/AngularJS/Pagination/dirPagination.tpl.html"></dir-pagination-controls>
</div>
</div>
</div>
</body>
</html>
you cannot use ng-click attribute on input with angularjs : https://docs.angularjs.org/api/ng/directive/input.
use onFocus javascript event
<input type="text" onfocus="myFunction()">
or try to surround your input with div or span and add ng-click on it.
I've got the working demo of your app, code (one-pager) is enclosed below, but here is the outline:
removed everything concerning dirPagination directive, replaced by ngRepeat
removed $log and replaced by console.log
since I don't have a Web API endpoint, I just populated $scope.Risks with some items on a rejected promise
Try adjusting your solution to first two items (of course, you won't populate it with demo data on rejected promise)
<!doctype html>
<html lang="en" ng-app="OpenBoxExtraModule">
<head>
<meta charset="utf-8">
<title></title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script>
var app = angular.module("OpenBoxExtraModule", []);
app.service('OpenBoxExtraService', function ($http) {
//Get All Risks
this.getAllRisks = function () {
return $http.get("/api/RiskApi");
}
});
app.controller("RiskController", function ($scope, OpenBoxExtraService) {
//On load
GetAllRisks();
function GetAllRisks() {
var promiseGet = OpenBoxExtraService.getAllRisks();
promiseGet.then(function (pl) { $scope.Risks = pl.data },
function (errorPl) {
console.log("Some error in getting risks.", errorPl);
$scope.Risks = [{RiskID: "1", i3_n_omr: "a", i3_n_2_uwdata_key: "b", RiskReference: "c", PureFacultative:"d", TimestampColumn: "e"}, {RiskID: "2", i3_n_omr: "a", i3_n_2_uwdata_key: "b", RiskReference: "c", PureFacultative:"d", TimestampColumn: "e"}, {RiskID: "3", i3_n_omr: "a", i3_n_2_uwdata_key: "b", RiskReference: "c", PureFacultative:"d", TimestampColumn: "e"} ];
});
}
$scope.ash = function () {
alert("Bananarama!");}
});
</script>
</head>
<body>
<div ng-controller="RiskController">
<table>
<thead>
<tr>
<th>Risk ID</th>
<th>i3_n_omr</th>
<th>i3_n_2_uwdata_key</th>
<th>Risk Reference</th>
<th>Pure Facultative</th>
<th>Timestamp</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="risk in Risks">
<td><span>{{risk.RiskID}}</span></td>
<td><span>{{risk.i3_n_omr}}</span></td>
<td><span>{{risk.i3_n_2_uwdata_key}}</span></td>
<td><span>{{risk.RiskReference}}</span></td>
<td><span>{{risk.PureFacultative}}</span></td>
<td><span>{{risk.TimestampColumn}}</span></td>
<td><input type="button" id="Edit" value="Edit" ng-click="ash()"/></td>
</tr>
</tbody>
</table>
<div>
<div></div>
</div>
</div>
</body>
</html>
Thank you all for your help, particularly #FrailWords and #Dalibar. Unbelievably, this was an issue of caching old versions of the javascript files. Doh!
You can't directly use then on your service without resolving a promise inside it.
fiddle with fallback data
this.getAllRisks = function () {
var d = $q.defer();
$http.get('/api/RiskApi').then(function (data) {
d.resolve(data);
}, function (err) {
d.reject('no_data');
});
return d.promise;
}
This will also fix your problem with getting alert to work.

bootstrap-table not rendering upon updating model in Angular

Hi I am not able to render table using bootstrap-table and angular. here is my code, I think I need to call bootstrap-table init method in angular ajax call. Can some one guide me on how to do this..?
angular
.module('reports')
.controller(
'ReportCtrl',
[
'$scope',
'$http',
'ngProgress',
function($scope, $http, ngProgress) {
var vm = this;
vm.mdp = {};
vm.mdp.data = [];
vm.mdp.columns = [];
$scope.submit = function() {
var report = $scope.tab;
$http.post('/reports/cmd/getData', {
report : report,
date : createdAfter
}).success(function(data) {
vm.mdp.data = data;
$.each(data[0], function(key, value){
vm.mdp.columns.push(key);
});
}).error(function(error) {
alert(error);
});
};
} ]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="mdp" class="panel" ng-controller="ReportCtrl as report" ng-show="panel.isSelected('mdp')">
<table data-toggle="table" data-show-columns="true" data-search="true" data-show-export="true" data-pagination="true" data-height="299">
<thead>
<tr>
<th ng-repeat="c in report.mdp.columns" data-field= {{c}} >{{ c }}</th>
</tr>
</thead>
<tr ng-repeat="r in report.mdp.data">
<td ng-repeat="c in report.mdp.columns">{{ r[c] }}</td>
</tr>
</table>
</div>
Integrating Bootstrap Table with Angular is solved here:
https://github.com/wenzhixin/bootstrap-table/issues/165
https://github.com/AkramKamal/bootstrap-table-examples/tree/master/integrate
I have some minor changes in my implementation of this solution which I will upload to Github / JSFiddle shortly. But the links above will allow you to get going.

AngularJS - HTML not updating on variable change

I am trying to learn AngularJS and i am making a test app.
I have a table that gets populated with data returned from a WebService (list of publishers) via $http.get().
When the user clicks a row (publisher) i want to fill a second table with the list of employees of the selected publisher. By using the F12 tools (Network+Console) i see that the data is returned but the second table is not filled/updated.
html
<!DOCTYPE html>
<html ng-app="myApp">
<head lang="en">
<meta charset="UTF-8">
<link rel="stylesheet" href="css/style.css" type="text/css" />
<script src=""></script>
<script src="js/angular.js"></script>
<script src="js/scripts.js"></script>
<script src="js/app.js"></script>
<title>My SPA</title>
</head>
<body>
<header>
<h1 id="page-title">Header</h1>
<nav>
<ul>
<li>Menu 1</li>
<li>Menu 2</li>
<li>Menu 3</li>
<li>Menu 4</li>
</ul>
</nav>
</header>
<div ng-controller='PublishersController' class="table-wrapper">
<table class="data-table" />
<thead>
<tr>
<th ng-repeat="(key,val) in publishers[0]">{{key}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='pub in publishers' ng-click='getPublishersEmployees(pub.pub_id)'>
<td ng-repeat='(key,val) in pub'>{{val}}</td>
</tr>
</tbody>
</table>
</div>
<div ng-controller='PublishersController' class="table-wrapper">
<table class="data-table" />
<thead>
<tr>
<th ng-repeat="(key,val) in employees[0]">{{key}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='employee in employees'>
<td ng-repeat='(key,val) in employee'>{{val}}</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
JS
var urlBase = "http://localhost:2041";
var app = angular.module('myApp', []);
app.factory('myFactory', ['$http', function ($http) {
var webAPI = '/api/query';
var webService = urlBase + webAPI;
var myFactory = {};
myFactory.getCategories = function () {
return $http.get(webService + '/getCategories');
};
myFactory.getCategorySalesByMonth = function (id) {
return $http.get(webService + '/getCategorySalesByMonth/' + id);
};
myFactory.getPublishers = function () {
return $http.get(webService + '/getPublishers');
};
myFactory.getPublishersEmployees = function (id) {
return $http.get(webService + '/getPublishersEmployees/' + id);
};
return myFactory;
}]);
app.controller('PublishersController', ['$scope', 'myFactory',
function ($scope, myFactory) {
$scope.status;
$scope.publishers;
$scope.employees;
getPublishers();
function getPublishers() {
myFactory.getPublishers()
.success(function (publishers) {
$scope.publishers = publishers;
})
.error(function (error) {
$scope.status = 'Unable to load publishers data: ' + error.message;
});
}
$scope.getPublishersEmployees = function (id) {
myFactory.getPublishersEmployees(id)
.success(function (employees) {
$scope.employees = employees;
console.log($scope.employees);
})
.error(function (error) {
$scope.status = 'Error retrieving employees! ' + error.message;
});
};
}]);
What am i doing wrong?
The problem is you use separate controllers for PublishersController and EmployeesController. Angular will create separate scopes for your controllers. Therefore, when you assign $scope.employees = employees in your PublishersController, it does not reflect on the scope created by EmployeesController
Try:
<div ng-controller='PublishersController' class="table-wrapper">
<table class="data-table" />
<thead>
<tr>
<th ng-repeat="(key,val) in publishers[0]">{{key}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='pub in publishers' ng-click='getPublishersEmployees(pub.pub_id)'>
<td ng-repeat='(key,val) in pub'>{{val}}</td>
</tr>
</tbody>
</table>
<table class="data-table" />
<thead>
<tr>
<th ng-repeat="(key,val) in employees[0]">{{key}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='employee in employees'>
<td ng-repeat='(key,val) in employee'>{{val}}</td>
</tr>
</tbody>
</table>
</div>
That solution above is just to point out your problem. I don't know your application design, you may not follow this solution but restructure your code to best fit your application design (like storing the employees in a shared service,...).
Here I propose another solution but I'm not sure if it fits with your application. You just use your original HTML code with PublishersController and EmployeesController. In your PublishersController, your could broadcast an event from rootScope:
.success(function (employees) {
$rootScope.$broadcast("employeeLoaded",employees);
})
Don't forget to inject $rootScope to your PublishersController:
app.controller('PublishersController', ['$scope', 'myFactory','$rootScope',
function ($scope, myFactory,$rootScope)
In your EmployeesController, you could subscribe to this event:
$scope.$on("employeeLoaded",function (event,employees){
$scope.employees = employees;
});
For more information about event in angular, check out Working with $scope.$emit and $scope.$on

Resources