AngularJS ng-click not firing controller method - angularjs

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.

Related

Can't retrieve data from controller AngularJS

I am learning AngularJS (so I'm a noob to this) I'm following a tutorial on Udemy. I even looked at the docs and have tried the wiring they have presented. I just can't seem to get the customers data in the table. What am I doing wrong and an explanation would be appreciated so I can learn the right way of AngularJS for the interview? Any help is much appreciated. By the way I'm using the latest version of AngularJS 1.7
(function () {
var CustomersController = function($scope) {
$scope.sortBy = 'name';
$scope.reverse = false;
$scope.customers = [{name:'sanjeet', joined:'2000-12-02', orderTotal: 10.096, age: 26}, {name:'gurpreet', orderTotal:201.961, joined:'2005-12-07',age: 24}, {name:'nikki', orderTotal: 14.561, joined:'2001-11-02', age: 25}];
$scope.doSort = function(propName) {
$scope.sortBy = propName;
$scope.reverse = !scope.reverse;
};
};
angular.module('app').contoller('CustomersController', CustomersController)
}())
// app.controller('CustomersController', ['$scope', function($scope) {
// $scope.sortBy = 'name';
// $scope.reverse = false;
//
// $scope.customers = [{name:'sanjeet', joined:'2000-12-02', orderTotal: 10.096, age: 26}, {name:'gurpreet', orderTotal:201.961, joined:'2005-12-07',age: 24}, {name:'nikki', orderTotal: 14.561, joined:'2001-11-02', age: 25}];
//
// $scope.doSort = function(propName) {
// $scope.sortBy = propName;
// $scope.reverse = !scope.reverse;
// };
// }])
<!DOCTYPE html>
<html ng-app>
<head>
<title>My first AngularJS project</title>
<link href="styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h3>Customers</h3>
Filter: <input type="text" ng-model="customerFilter.name"/>
<br />
<table ng-controller="CustomersController">
<tr>
<th ng-click="doSort('name')">
Name
</th>
<th ng-click="doSort('age')">
Age
</th>
<th ng-click="doSort('joined')">
Joined
</th>
<th ng-click="doSort('orderTotal')">
Order Total
</th>
</tr>
<tr ng-repeat="customer in customers | filter: customerFilter | orderBy:sortBy:reverse" >
<td>
{{customer.name}}
</td>
<td>
{{customer.age}}
</td>
<td>
{{customer.joined | date: 'yyyy-MM-dd'}} <!--medium, longDate -->
</td>
<td>
{{customer.orderTotal | currency: 'y'}}
</td>
</tr>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
<script src="app/controllers/customersController.js"></script>
<script> var app = angular.module('app', [])</script>
</body>
</html>
You have multiple issues causing your app to not load. You should consider using angular.js rather than angular.min.js to receive better error messages in the console, which would help you to identify your errors.
You have a typo in your controller code. angular.module('app').contoller('CustomersController', CustomersController). .controller is missing an r.
You cannot use <html ng-app> in newer releases of angular (1.3+). This is a very old syntax. The correct syntax is to identify the app module. <html ng-app="app">.
Your App module must be defined before the controllers that use it. i.e.
<script> var app = angular.module('app', [])</script>
has to come before
<script src="app/controllers/customersController.js"></script>
Your Filter: <input type="text" ng-model="customerFilter.name"/> line is outside the controller, and thus won't function. You should move the ng-controller="CustomersController" to the body instead of the table, or a wrapping div.
I created a plunker and updated your code, showing the app in a functional status.

Displaying data using 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.

How to show table data in separate page in AngularJS

This is my dashboard.html where all the user data will display from controller file. Now what I want is that when I click the button of each user it will display the information of user in a separate page.
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.min.js"></script>
<script src="newcontroller.js"></script>
<script src="controller.js"></script>
<link rel="stylesheet" href="stylingpage.css">
</head>
<body ng-app="myModule">
<div ng-controller="myCtrl">
<h2 align="center">Welcome</h2>
<table width="20%">
<thead>
<tr>
<th>ID</th>
<th>UserName</th>
<th>Password</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="employee in employees">
<td>{{employee.id}}</td>
<td>{{employee.name}}</td>
<td>{{employee.password}}</td>
<td><button type="button" ng-click="view()">View</button></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
When I click the View button it will display that person info in separate page. How can I do it? Please help. Thanks in advance.
This is my controller.js file:
var app=angular.module('mainApp',['ngRoute']);
app.config(function($routeProvider){
$routeProvider
.when('/',{
templateUrl:'login.html'
})
.when('/newdashboard',{
resolve:{
"check":function($location,$rootScope){
if(!$rootScope.loggedIn){
$location.path('/');
}
}
},
templateUrl:'newdashboard.html'
})
.when('/userdetails',{
templateUrl:'userdetails.html'
})
.otherwise({
redirectTo:'/'
});
});
app.controller('loginCtrl',function($scope,$location,$rootScope){
$scope.submit=function(){
if($scope.username=='admin' && $scope.password =='admin'){
$rootScope.loggedIn=true;
$location.path('/newdashboard');
}else{
alert('wrong Username or password. Try Again');
}
};
});
app.controller('myCtrl',function($scope){
$scope.employees=[
{id:"101",name:"User 1",password:"User1#123"},
{id:"102",name:"User 2",password:"User2#123"},
{id:"103",name:"User 3",password:"User3#123"},
{id:"104",name:"User 4",password:"User4#123"},
{id:"105",name:"User 5",password:"User5#123"},
{id:"106",name:"User 6",password:"User6#123"}
];
});
i believe there's more than enough ways to do this just search "passing objects between controllers angularjs" google can get you more than enough results.. it's either done by passing the object in URL, a service ,or using local storage.
common things are
you'll need a controller for the details page
you'll probably need to pass the employee object in the view() function --> view(employee)
You can do it, in following way.
Step 1 - Update your HTML to pass, employee Id as parameter in "view" method
<td><button type="button" ng-click="view(employee.id)">View</button></td>
Step 2 - Update routing state to send the ID as parameter for detail page.
.when('/userdetails/:id',{
templateUrl:'userdetails.html'
})
Step 3 - Write the "view" function to change state from listing page to detail page. Add it in your "myCtrl" method
$scope.view= function(userId) {
$location.path('/userdetails/').search({id: userId});
}
Step 4 - To get parameter on detail page(In controller method) in following way.
var urlParams = $location.search();
urlParams.id will return Empolyee Id
So now you have selected employee Id on detail page controller, so you can bind the details of that employee to view.

Angular JS - dynamically add custom href link to value in table using ng-repeat based on a different value.

I am creating a table using ng-repeat that display some tickets info. Currently in the column "Ticket No" I am adding href link (when user click on the "Ticket No" it will open new tab and the URL will take the ticket no as parameter.
This a plunker I've created so it can show functionality as described above http://plnkr.co/edit/GB8WWz?p=preview
The problem I have now is that the href link might vary and it depends on the account column value. So if my "account = foo" set the href link of the Ticket No to "http://myfoopage.foo/ticketid...etc". If my "account = boo" set the href link for the Ticket No to "http://myboopage.boo/ticketid...etc".
Any idea on how to approach that ?
scriptang.js
angular.module('plunker', ['ui.bootstrap']);
function ListCtrl($scope, $dialog) {
$scope.items = [
{ticket: '123', description: 'foo desc',account:'foo'},
{ticket: '111', description: 'boo desc',account:'boo'},
{ticket: '222', description: 'eco desc',account:'eco'}
];
}
// the dialog is injected in the specified controller
function EditCtrl($scope, item, dialog){
$scope.item = item;
$scope.save = function() {
dialog.close($scope.item);
};
$scope.close = function(){
dialog.close(undefined);
};
}
index.html
<!doctype html>
<html ng-app="plunker">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
<script src="http://angular-ui.github.com/bootstrap/ui-bootstrap-tpls-0.1.0.js"></script>
<script src="scriptang.js"></script>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.0/css/bootstrap-combined.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="ListCtrl">
<table class="table table-bordered">
<thead>
<tr>
<th>Ticket No</th>
<th>Description</th>
<th>Account</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items">
<td>{{item.ticket}}</td>
<td>{{item.description}}</td>
<td>{{item.account}}</td>
<td><button class="btn btn-primary" ng-click="edit(item)">Edit</button></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Updated plnkr here, I've made use of the ng-attr directive in combination with a function that creates an url.
$scope.getUrl = function (item) {
var url = '';
if(item.account === 'foo')
url = 'http://mywebpage.foo';
else
url = 'http://mwebpage.boo';
url += '/ticketid='+item.ticket
return url;
}

angular $injector:unpr Error

Im trying to use Resource in my app and I get the following error:
$injector:unpr
"errors.angularjs.org/1.3.15/$injector/unpr?p0=mkResourceProvider%20%3C-%20mkResource%20%3C-%20mkController".
Here is my Code
app
var logApp = angular.module('mkApp', ['ngResource','ngRoute']);
Controller
angular.module('mkApp').controller('mkController', function ($scope, mkResource) {
$scope.ddl = [];
mkResource.LookUp(function (data) {
$scope.ddl = data;
console.log($scope.ddl);
});});
Resource
angular.module('mkApp').factory('mkResource', function ($resource, $http) {
var lookup = $resource('api/HowOftens');
function LookUp() {
return lookup.query();
}
return {
LookUp: LookUp
}});
HTML
<head>
<script src="../Scripts/angular.min.js"></script>
<script src="../Scripts/jquery-2.1.3.min.js"></script>
<title></title>
<div ng-app="mkApp">
<div ng-controller="mkController">
<table>
<tr>
<td> F Name</td>
<td> L Name</td>
</tr>
<tr>
<td><input type="text" /></td>
<td><input type="text" /></td>
</tr>
<tr>
<td>
<slect></slect>
</td>
</tr>
</table>
</div>
</div>
<script src="MkApp/MkApp.js"></script>
<script src="Controller/MkController.js"></script>
<script src="../Scripts/angular-resource.min.js"></script>
<script src="../Scripts/angular-route.min.js"></script>
From all the reading ive been doing i understand its injection error. I don't understand what Im not injecting properly though. The final plan was to load ddls from data I will receive.
You would need to be loading your angular-route and angular-resource (your libs) before you actually load up your angular app files.

Resources