I am implementing logic through ui-router, Factory and Directive but getting error: JavaScript runtime error: [$injector:modulerr] in Angular Js.
Ui-Routing was working fine.
Index.html file:
<html><head><title>Employee Management System</title>
<link href="Content/bootstrap.css" rel="stylesheet" />
<script src="Scripts/jquery-1.9.1.min.js"></script>
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/angular-ui-router.min.js"></script>
<script src="Scripts/bootstrap.min.js"></script>
<script src="Scripts/app/EmpRecord.js"></script>
<script src="Scripts/app/GetDataService.js"></script>
<script src="Scripts/app/EmpController.js"></script>
<script src="Scripts/app/EmpApp.js"></script></head>
<body ng-app="EmpApp">
<div class="page-header">Employee Management System
</div><div ng-include="'pageContents/menu.html'"></div>
<ui-view></ui-view></body></html>
EmpApp.js
var app = angular.module("EmpApp", ['ui.router']);
app.factory('EmpFact', ['$http', EmpFact])
.controller('EmpController', ['$scope', 'EmpFact',EmpController])
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
templateUrl: '/home.html'
})
.state('Add', {
templateUrl: '/AddEmployee.html'
})
.state('List', {
templateUrl: 'ListEmp.html',
controller: 'EmpController'
}
)
})
.directive('emp-Record', EmpRecord);
ListEmp.html:
<div><div><h3>List of Employees</h3></div>
<div EmpRecord ng-repeat="e in Employees"></div></div>
EmpController
<div><div><h3>List of Employees</h3></div>
<div EmpRecord ng-repeat="e in Employees"></div></div>
GetDataService.js
var EmpFact = function ($http) {
var records = {}
$http.get('http://localhost/EmployeeApi/api/Emp')
.then(function (response) {
records= response.data;
});
return {
GetData: function () {
alert(records);
return records;
}
}
}
All Errors are gone Now but data is not coming.
In short:
Controller:
var EmpController= function ($scope,EmpFact) {
$scope.Employees = EmpFact.GetData();
console.log($scope.Employees);
};
Service:
var EmpFact = function ($http) {
var records = {}
$http.get('http://localhost/EmployeeApi/api/Emp')
.then(function (response) {
records= response.data;
});
return {
GetData: function () {
alert(records);
return records;
}}}
Àpp.js
app.factory('EmpFact', ['$http', EmpFact])
.controller('EmpController', ['$scope','EmpFact', EmpController])
.directive('empRecord', function () {
return {
template: "<tr><td>{{e.empid}}</td><td>{{e.empName}}</td><td>{{e.empEmail}}</td><td>{{e.empSalary}}</td>"
}});
HTML:
<div>
<div><h3>List of Employees</h3></div>
<div emp-Record ng-repeat="e in Employees"></div>
</div>
Ok, so as I suggested in the comment, because the error implies that you haven't injected the EmpFact factory into EmpController, changing
.controller('EmpController', ['$scope', EmpController])
Into:
.controller('EmpController', ['$scope', 'EmpFact', EmpController])
And also injecting it to the controller function:
var EmpController = function ($scope, EmpFact) { ... };
Made the error disappeared, but now you say that "data is not coming".
I suggest another change in your factory, instead of your current code, try this:
var EmpFact = function ($http) {
return {
GetData: function () {
// return a promise which resolve with the actual data returned from the server
return $http.get('http://localhost/EmployeeApi/api/Emp').then(
function (response) {
// return the actual results, instead of the whole response from the server
return response.data;
}
);
}
}
};
Now, in your controller, you should be able to get the data like this:
var EmpController = function ($scope, EmpFact) {
// Call the "GetData" from the factory, which return a promise with the actual results returned from the server
EmpFact.GetData().then(
function(data) {
// in the resolve callback function, save the results data in
// any $scope property (I used "$scope.Employees" so it will be
// available in the view via {{ Employees | json }})
$scope.Employees = data;
}
);
};
By returning a promise you are guaranteed to be able to handle the results returned from an asynchronous request (AJAX). You should be able to use the results in the view like this:
<div emp-Record ng-repeat="e in Employees"></div>
(Note that the above HTML snippet is taken from the comments below this answer)
Edit:
Looking at your directive, it doesn't look like a correct way to construct a table. Change emp-Record to emp-record and wrap it in a <table> tag to make it a valid HTML:
<table>
<tr emp-record ng-repeat="e in Employees"></tr>
</table>
And in your directive's template make sure you close the row tag (Add </tr>):
.directive('empRecord', function () {
return {
template: "<tr><td>{{e.empid}}</td><td>{{e.empName}}</td><td>{{e.empEmail}}</td><td>{{e.empSalary}}</td></tr>"
}
});
Thanks Alon for your help as I am new to Angular, converting my ASP.NET MVC code to HTML5/Angular only.
Finally I am able to resolve it.
Data Service/Factory:
var EmpFact = function ($http) {
return {
GetData: function () {
return $http.get('http://localhost/EmployeeApi/api/Emp');
}
}
}
Controller:
var EmpController = function ($scope, EmpFact) {
//EmpFact.GetData() is a promise.
EmpFact.GetData().then(
function (result) {
$scope.Employees= result.data;
}
);
}
Related
angular js not displaying anything even like simple expressions. i am tying to execute below code but no hope. can anyone help me out.
below code is for view to display.
`<html>
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script type="text/javascript" src="/../../Scripts/angularsample.js"></script>
</head>
<body ng-app="spiceApp">
<div>
<div ng-controller="SpicyController">
<p> lets try some code by using service </p>
<input ng-init="message='Girish'" ng-model="message" />
<button ng-click="notify(message);">Notify{{1+2}}</button>
<p>alert will display only by clicking three times.</p>
</div>
<div ng-controller="List">
<button ng-click="bringList()">getList</button>
<table>
<tr ng-repeat="app in appslist">
<td>
{{app.Name}}
</td>
</tr>
</table>
</div>
</div>
</body>
</html>`
js code
var myApp = angular.module('spiceApp', []);
myApp.controller('SpicyController', ['$scope', '$http', 'userService', , function ($scope, $http, userService) {
//below code is using sservice
$scope.notify = function (msg) {
userService(msg);
};
}]);
myApp.controller('List', ['$scope', 'getList', function ($scope, getList) {
$scope.bringList = function () {
getList.getAppsList().then(function (list) {
$scope.appslist = list;
});
};
}]);
myApp.factory('getList', ['$http',function ($http) {
//this code for getting list from controller.
return getList.getAppsList=function(){
$http({
method: 'GET',
url: 'Home/GetAppsList'
})
.success(function (response) {
return response.data;
}, function (error) {
console.log(error);
});
}
}]);
myApp.factory('userService', ['$window', function (win) {
var msgs = [];
return function (msg) {
msgs.push(msg);
if (msgs.length == 3) {
win.alert(msgs.join('\n'));
msgs = [];
}
};
}]);`
please tell me where i am wrong. nothing is working. expression is displaying like {{1+2}} in the ouptut.
You have a typo here:
myApp.controller('SpicyController', ['$scope', '$http', 'userService', , function
with the 2 comas so the dependancies are messed up.
i tried in different way with same view but i modified the js file now it's working fine.
var myApp = angular.module('spiceApp', []);
myApp.controller('SpicyController', ['$scope', '$http', 'userService',function ($scope, $http, userService) {
//below code is using sservice
$scope.notify = function (msg) {
userService(msg);
};
}]);
myApp.factory('userService', ['$window', function (win) {
var msgs = [];
return function (msg) {
msgs.push(msg);
if (msgs.length == 3) {
win.alert(msgs.join('\n'));
msgs = [];
}
};
}]);
myApp.controller('List', ['$scope', 'getList', function ($scope, getList) {
$scope.bringList = function () {
getList.getAppsList.then(function (data) {
$scope.appslist = data;
});
};
}]);
var getList = angular.module("spiceApp").factory("getList", ['$http', function ($http, getList) {
return {
getAppsList: (function (response) {
return $http({
method: 'GET',
url: 'GetAppsList'
})
.then(function (response) {
console.log("coming from servicejs", response.data);
//return data when promise resolved
//that would help you to continue promise chain.
return response.data;
});
})()
};
return getList;
}]);
I don't know how to make a service for a json file and call this service in my controller.
I have one controller in my app,and so must remain.
Try to run this example via run code snippet blue button.
Basically, You need to declare that service, the require it via Angular.DI, lastly call the service method and wait for its result.
Hope it helps
angular
.module('test', [])
.constant('API' , 'https://jsonplaceholder.typicode.com')
.service('TestService', function(API, $http) {
this.getData = function() {
return $http
.get(API + '/photos')
.then(function(response) {
return response.data;
})
};
})
.controller('TestCtrl', function($scope, TestService) {
//But a Resolve is preferred
TestService
.getData()
.then(function(data) {
$scope.album = data;
})
;
})
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<section ng-app="test">
<article ng-controller="TestCtrl">
<div ng-repeat="photo in album">
<h3 ng-bind="photo.title"></h3>
<img ng-src="{{photo.thumbnailUrl}}" />
</div>
</article>
</section>
You have to call your service from your controller.
your service:
angular.module('YOURAPP')
.service("userAService", function ($http) {
this.promise= function () {
return $http.get('resources/json/data.json')
}
});
And then in your controller function:
mycontroller = function(userAService){
userAService.promise().then(
function(response){
//do what you want in your promise
// try console.log(response.data) to see if you get your data.
}
)
}
I have the following HTML structure:
<div ng-controller="MainController">
<div ng-repeat="row in rows">
[[row.id]]
</div>
<div ng-controller="SubController">
<div ng-repeat="row in rows">
[[row.id]]
</div>
</div>
</div>
Angular code is:
myApp.controller('MainController', function ($scope, $http) {
$http.get('/foo/ajaxGetSomeData/').then(function (response) {
$scope.rows = response.data;
});
});
myApp.controller('SubController', function ($scope, $http) {
$http.get('/bar/ajaxGetAnotherThing/').then(function (response) {
var parentRows = $scope.$parent.rows;
var newRows = parentRows.merge(response.data);
$scope.rows = newRows;
});
});
The problem here is that sometimes the first request executes after the second. And the second depends on the first, so I'm getting an error.
How could I solve this?
Below elaborates a bit more on my comment. Here we would initialize both promises inside the DataRows service (through call to initData from MainController). The SubController is no longer dependent on MainController, but just the fact that something else has called initData. If something else hasn't called that function, then you will get console errors for calling "then" on undefined object.
I also used $timeout instead of $http to mock out async work. I don't know what your data looks like, so I just made an array of strings, you should be able to adapt.
angular.module('myApp', [])
// Using $timeout instead of $http for demo
.service('DataRows', function ($http, $q, $timeout) {
var someData,
anotherThing;
this.initData = function () {
// actual call. get rid of $timeout line in actual code
// someData = $http.get('/foo/ajaxGetSomeData/').then(function (response) {
someData = $timeout(function () { return {data: ['parentRow1', 'parentRow2', 'parentRow3']}; }, 1500).then(function (response) {
return response.data;
});
anotherThing = someData.then(function (parentRows) {
// actual call. get rid of $timeout line in actual code
// return $q.all([parentRows, $http.get('/bar/ajaxGetAnotherThing/')]);
return $q.all([parentRows, $timeout(function () {return {data: ['childRow1', 'childRow2', 'childRow3']}}, 1500)]);
}).then(function (promises) {
var parentRows = promises[0],
response = promises[1];
// from your original code -- merge is not available here. Mocking concatted rows from first call
// return parentRows.merge(response.data);
return parentRows.concat(response.data);
});
};
this.getSomeData = function () {
return someData;
};
this.getAnotherThing = function () {
return anotherThing;
};
})
.controller('MainController', function ($scope, DataRows) {
// initData first so both promises are ready
DataRows.initData();
// getSomeData is the first promise (call to /foo/ajaxGetSomeData)
DataRows.getSomeData().then(function (rows) {
$scope.rows = rows;
});
})
.controller('SubController', function ($scope, DataRows) {
// getAnotherThing is the second promise that depends on the first (/bar/ajaxGetAnotherThing)
DataRows.getAnotherThing().then(function (newRows) {
$scope.rows = newRows;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MainController">
<div ng-repeat="row in rows">
{{row}}
</div>
<div ng-controller="SubController">
<div ng-repeat="row in rows">
{{row}}
</div>
</div>
</div>
I have created a simple app to store an event to my database. It is working fine but with a wordaround.
I use the following method:
controllers.controller('CalendarAddController', function($scope, $routeParams, Event) {
$scope.addEvent = function() {
$scope.ev=new Event();
$scope.ev.title = $scope.event.title;
$scope.ev.$save().then(function(res) { console.log("success");})
.catch(function(req) { console.log("error saving obj"); })
.finally(function() { console.log("always called") });
}
});
After submitting my form, the function addEvent is called.
If I print the value of $scope.event, it has the right values.
However, when I call .$save() on it, I get the error "TypeError: $scope.event.$save is not a function."
But when I create a new object and assign the values to it, it works fine.
Why isn't it working directly? Always creating a dummy object does not seem to be best practice I suppose.
The service I created
services.factory( 'Resource', [ '$resource', function( $resource ) {
return function( url, params, methods ) {
var defaults = {
update: { method: 'put', isArray: false },
create: { method: 'post' }
};
methods = angular.extend( defaults, methods );
var resource = $resource( url, params, methods );
resource.prototype.$save = function() {
if ( !this.id ) {
return this.$create();
}
else {
return this.$update();
}
};
return resource;
};
}]);
services.factory( 'Event', [ 'Resource', function( $resource ) {
return $resource( '/api/calendar/:id' );
}]);
Update: basic example
Using this example everything works front-end but in my rest API the data is not passed.
<!DOCTYPE html>
<html lang="en-US">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular-resource.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular-route.min.js"></script>
<script type="text/javascript">
var app = angular.module('app', ['ngRoute','ngResource'])
.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl : 'pages/home.html',
controller : 'mainController'
})
});
app.factory('Event', function($resource) {
return $resource('/test/api/:id');
});
app.controller('mainController', ['$scope', '$routeParams', 'Event',
function($scope, $routeParams, Event) {
function handleSuccess(data) {
alert("success");
}
function handleError(data) {
alert("error");
}
var event = new Event();
event.title = "a title";
Event.save(event, handleSuccess, handleError);
}]);
</script>
<body>
<div ng-app="app">
<div ng-view></div>
</div>
</body>
</html>
For the back-end I created a very basic script which writes the request to a file:
It always says "array()" so no data is passed.
<?php
$myFile = "testFile.txt";
$fh = fopen($myFile, 'w') or die("can't open file");
$stringData = print_r($_REQUEST,true);
fwrite($fh, $stringData);
fclose($fh);
?>
Where do you initialize $scope.event or is it automatically created by angular? If this is an plain JavaScript object you can't call .$save, but you can use the Event service itself - no need to create a new instance:
Event.create($scope.event)
I am building a service in angular and injecting the service in controller. I am trying to fetch data from json file and am using $http. however the data is not getting returned and i get undefined.
I am updating my code as per suggestion by #Phil
Service.js
;(function(app) {
app.factory('authService', ['$log', '$http','$location', function($log, $http,$location) {
var url = 'js/user.json';
var authService= {};
var userExist=null;
authService.authenticate = function(userid) {
var userobj = $http.get(url).success(function (data) {
userExist = data
console.log(data);
return userExist;
$log.info("Loaded users");
})
.error(function (error) {
$log.info(error);
$log.info("No user exists");
return error;
})
return userobj;
}
return authService;
}]);
})(angular.module('userApp'));
Controller.js
;(function(app) {
app.controller('Controller', ['$scope', '$log','$location','authService', function($scope,$log,$location,authService) {
$scope.data={};
$scope.getUsers = function()
{
userid = "123";
$scope.data = authService.authenticate(userid);
console.log($scope.data);
return $scope.data ;
}
}])
}(angular.module('userApp')));
index.html
<div class="main" ng-controller="Controller">
<input type="button" name="btngetusers" ng-click="getUsers()"></input>
</div>
<script src ="js/app.js"> </script>
<script src ="js/controller/Controller.js"> </script>
<script src ="js/services/Service.js"> </script>
user.json
i have placed the json file under the js directory.
[
{
"UserId": "1",
"FName": "Hice",
"LastName": "Harry"
},
{
"UserId": "2",
"FName": "Andrew",
"LastName": "Ads"
}
]
The data is getting returned as undefined. what am i missing here?
UPDATED CODE
I am updating my code as per suggestion by #skubsi
Service.js
;(function(app) {
app.factory('authService', ['$log', '$http','$location', function($log, $http,$location) {
var url = 'js/user.json';
var authService = {};
var userExist=null;
authService.authenticate = function(userid,success,error) {
$http.get(url).success(function(data){
success(data);
})
.error(error);
};
return authService;
}]);
})(angular.module('userApp'));
Controller.js
;(function(app) {
app.controller('MainController', ['$scope', '$log','$location','authService', function($scope,$log,$location,authService) {
var self = this;
this.data = null;
this.getUsers = function(){
function success(response){
self.data = response;
}
function error(){
console.log("error");
}
authService.authenticate(1,success,error);
}
}])
}(angular.module('userApp')));
index.html
<div class="main" ng-controller="MainController as main">
{{main.data}}
<input type="button" name="btngetusers" value ="Get User" ng-click="main.getUsers()"></input>
</div>
<script src ="js/app.js"> </script>
<script src ="js/controller/MainController.js"> </script>
<script src ="js/services/authenticate.js"> </script>
First things first: your JSON is invalid, you can verify this yourself by entering the JSON you supplied in JSONLint.
Parse error on line 2:
[ { UserId: 123,
--------------^
Expecting 'STRING', '}'
Secondly you pass a unknown service into your controller:
authenService
Then you should realize a promise is code that will run asynchronously, meaning that:
userid = "123";
$scope.data = authService.authenticate(userid);
console.log($scope.data);
return $scope.data ;
will not run synchronously. console.log($scope.data); Will be executed long before your authenticate method will be done. So you need to find a way to make your controller handle accordingly whilst keeping concerns separated. (and not falling into a deferred-anti-pattern).
You could for example add additional parameters to your authenticate function, which will enable the function to call back the original caller.
authService.authenticate = function(userid, success, error) { //success and error are functions
$http.get(url).success(function(data) {
//separation of concerns:
//execute logic.. set flags, filter w/e belongs to your authentication process.
success(data);
})
.error(error); //no processing required
};
So that in your controller all that is left to do is calling the authService and providing it a way to set your data:
this.getUsers = function() {
//This will enable to set the response to your controllers data model.
function success(response) {
self.data = response;
window.alert(response);
}
function error() {
window.alert('shite happened');
}
authService.authenticate(1, success, error);
};
Note that I have used the controllerAs syntax instead of $scope. To prove this mechanism works I created a plunker for you to investigate.
Your authenticationService.authenticate method doesn't return anything.
Specifically, the service name is authService and you're calling authenticationService.authenticate.