This is my module.js
var app = angular.module("ApplicationModule", ["ngRoute"]);
app.factory("ShareData", function () {
return { value: 0 }
});
//Showing Routing
app.config(['$routeProvider', '$locationProvider', function
($routeProvider, $locationProvider) {
debugger;
$routeProvider.when('/ShowAll',
{
templateUrl: 'Home/ShowAll',
controller: 'ShowAllController'
});
$routeProvider.otherwise(
{
redirectTo: '/'
});
}]);
This is my Services.js
app.service("SampleService", function ($http) {
this.getSamples = function () {
return $http.get("/api/Sample");
};
this.getSample = function (id) {
return $http.get("/api/Sample" + id);
};
});
This is my ShowAllController.js
app.Controller('ShowAllController', function ($scope,
SampleService) {
loadAll();
function loadAll() {
var promiseGet = SampleService.getSamples();
promiseGet.success(function (data) { $scope.Samples = data
},
function (errordata) {
$scope.error = errordata;
}
);
}
});
This is my index.cshtml
#{
ViewBag.Title = "API's";
}
#section scripts{
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-route.min.js"></script>
<script src="~/Scripts/Module.js"></script>
<script src="~/Scripts/Services.js"></script>
<script src="~/Scripts/ShowAllController.js"></script>
}
<div class="container" data-ng-app="ApplicationModule">
<div class="panel panel-default">
<div class="panel-header">
<div class="row">
<div><h4 class="col-xs-6">GET api/Patient</h4>Patients List</div>
</div></div>
<div class="panel-body" data-ng-view>
</div>
</div>
This is my partial view (ShowAll.cshtml)
<div data-ng-controller="ShowAllController">
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>Age</th>
<th>Address</th>
</tr>
<tr data-ng-repeat="person in Samples">
<td>{{person.Id}}</td>
<td>{{person.Name}}</td>
<td>{{person.Age}}</td>
<td>{{person.Address}}</td>
</tr>
</table>
</div>
My return PartialView code is in my HomeController inside the ShowAll ActionResult. The problem is that when I click the button it just displays the header of the table without the data.
Note: This is a web api.
Thank you.
Add the following statement to your ShowAllController before the ajax call so Angular is aware of this scope var in Config time
app.Controller('ShowAllController', function ($scope, SampleService) {
$scope.Samples = []; // <- NEW LINE HERE!
loadAll();
function loadAll() {
var promiseGet = SampleService.getSamples();
promiseGet.success(function (data) { $scope.Samples = data
},
function (errordata) {
$scope.error = errordata;
}
);
}
});
Angular Dependency Injection might not be setting up the scope var Samples in Config time. Then in Run time, it won't recognize this var as something that should be updated.
If that doesn't work, also try to wrap the success result of of your promise into $scope.$apply() as angular might not be aware of it when running its digest function.
$scope.$apply(function () {
$scope.Samples = data;
})
Related
I'm trying to get ui-router's resolve to pass its value to the controller portalsForUserCtrl.
Here is the router:
(function () {
'use strict';
var myApp = angular.module("myApp", ["common.services", "ui.router", 'ngMessages']);
myApp.config(["$stateProvider", "$urlRouterProvider",
function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/");
$stateProvider
.state("portalsForUser", {
url: "/userPortal/portalsForUser/:id",
templateUrl: "app/userPortal/portalsForUser.html",
controller: "portalsForUserCtrl as vm",
resolve: {
userPortalService: "userPortalService",
portalsForUser: function (userPortalService, $stateParams) {
var userId = $stateParams.id;
console.log(userId); //shows userId correctly
return userPortalService.getPortalsForUserPromise(userId)
.then(function (response) {
var userPortals = response.data;
console.log("userPortals", userPortals); //shows portals
return userPortals;
});
}
}
})
}]
);
Here is the entire controller:
(function () {
"use strict";
angular.module("myApp")
.controller("portalsForUserCtrl", portalsForUserCtrl);
portalsForUserCtrl.$inject = ['portalsForUser', 'userPortalService'];
function portalsForUserCtrl(portalsForUser, userPortalService) {
console.log("in portalsForUserCtrl");
var vm = this;
vm.portalsForUser = portalsForUser;
console.log(portalsForUser);
}
}());
In mainCtrl, which is the controller for index.html, I call:
$state.go("portalsForUser", ({ "id": userId }));
Here is the code for the view app/userPortal/portalsForUser.html:
<div class="container">
<table class="table table-condensed table-striped table-bordered">
<tbody>
<tr>
<th class="col-md-2"> </th>
<th class="col-md-4">
Portal Name
</th>
</tr>
<tr ng-repeat="userPortal in vm.portalsForUser">
<td>
{{userPortal.portal.portalName}}
</td>
<td class="">
<a class="btn btn-primary" ui-sref="goSomewhere({id: userPortal.portal.id})">
Go
</a>
</td>
</tr>
</tbody>
</table>
Here is the code for the userPortalService:
(function () {
"use strict";
angular.module("myApp")
.service('userPortalService', userPortalService);
userPortalService.$inject = ['userPortalResource', '$http', 'appSettings']
function userPortalService(userPortalResource, $http, appSettings) {
var getPortalsForUserPromise = function (id) {
return $http.get(appSettings.serverPath + '/api/UserPortal/GetPortalsForUser/' + id);
};
return {
getPortalsForUserPromise: getPortalsForUserPromise
};
}
}());
The url changes to the correct /userPortal/portalsForUser/:id but the portalsForUserCtrl function does not fire. It is only when I hit enter on the same url that portalsForUserCtrl is instantiated and the data appears in the view. What am I missing?
You have a syntax error in the $state.go statement.
Change this:
$state.go("portalsForUser", ({ "id": userId }));.
to this:
$state.go("portalsForUser", { "id": userId });
On the documentation (https://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$stateProvider) the specification of the method mentions the following:
The map object is:
key - {string}: name of dependency to be injected into controller
factory - {string|function}: If string then it is alias for service.
Otherwise if function, it is injected and return value it treated as
dependency. If result is a promise, it is resolved before its value is
injected into controller.
with the following as an example:
resolve: {
myResolve1:
function($http, $stateParams) {
return $http.get("/api/foos/"+stateParams.fooID);
}
}
So I suggest you change your code into one of these options to make it as simple a possible and, using chrome developer tool, place a breakpoint on the first line on the method:
resolve: {
portalsForUser: ['userPortalService', '$stateParams', function (userPortalService, $stateParams) {
var userId = $stateParams.id; //place your breakpoint here
return userPortalService.getPortalsForUserPromise(userId);
}]
}
Check what is going on with $stateParams; it is not impossible that, for some reason, at this moment, everything is not initialized yet because values don't come from the url, therefore, the id property is undefined. Try to inject "$state" and see if $state.params.id contains what you expect instead. (like mentioned in here: https://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state).
Here is what it could look like:
resolve: {
portalsForUser: ['userPortalService', '$state', function (userPortalService, $state) {
var userId = $state.params.id; //place your breakpoint here
return userPortalService.getPortalsForUserPromise(userId);
}]
}
Hope that if it doesn't solve your problem, at least it will help you to find it.
EDIT:
It seems all the previous doesn't go to the right direction.
Here is my new direction:
I used your plunker to create a hosted site on my computer (using http-server: https://www.npmjs.com/package/http-server). My version that doesn't seem to be very different than yours works perfectly. Here is the full code:
app.js:
(function () {
'use strict';
var myApp = angular.module("myApp", ["ui.router"]);
myApp
.config(config)
.controller("portalsForUserCtrl", portalsForUserCtrl)
.service('userPortalService', userPortalService)
.controller("mainCtrl", mainCtrl)
mainCtrl.$inject = ["userPortalService", "$state"];
function mainCtrl(userPortalService, $state) {
var vm = this;
vm.clickMe = function () {
var userId = 1;
$state.go("portalsForUser", { "id": userId });
}
};
config.$inject=["$stateProvider"];
function config($stateProvider) {
$stateProvider
// PortalsForUser GET
.state("portalsForUser", {
url: "/userPortal/portalsForUser/:id",
templateUrl: "portalsForUser.html",
controller: "portalsForUserCtrl as vm",
resolve: {
portalsForUser: ['userPortalService', '$stateParams', function (userPortalService, $stateParams) {
return userPortalService.getPortalsForUserPromise($stateParams.id).then(function(response){return response.data;});
}]
}
})
}
userPortalService.$inject = ['$http', '$q', '$timeout']
function userPortalService($http, $q, $timeout) {
var getPortalsForUserPromise = function (id) {
var myId=id;
var deferred=$q.defer();
$timeout(function(){
deferred.resolve({data:[
{
id: 16,
portal: {
portalName: "Portal1-" + myId,
portalId: 1
}
},
{
id: 17,
portal: {
portalName: "Portal2-" + myId,
portalId: 2
}
}
]});
},5000);
return deferred.promise;
};
return {
getPortalsForUserPromise: getPortalsForUserPromise
};
};
portalsForUserCtrl.$inject = ['portalsForUser', 'userPortalService'];
function portalsForUserCtrl(portalsForUser, userPortalService) {
console.log("in portalsForUserCtrl");
var vm = this;
vm.portalsForUser = portalsForUser;
console.log(portalsForUser);
};
}());
index.html:
<html>
<head></head>
</html>
<body ng-app="myApp">
<!-- bower:js -->
<script src="/bower_components/angular/angular.js"></script>
<script src="/bower_components/angular-ui-router/release/angular-ui-router.js"></script>
<!-- endbower -->
<!-- inject:js -->
<script src="app.js"></script>
<!-- endinject -->
<body ng-app="myApp" ng-controller="mainCtrl as vm">
<button type="submit" class="btn btn-default" ng-click="vm.clickMe()">
Click Me
</button>
<div ui-view></div>
</body>
</body>
portalsForUser.html:
<div class="container">
Portals For User
<table class="table table-condensed table-striped table-bordered">
<tbody>
<tr>
<th class="col-md-2"> </th>
<th class="col-md-4">
Portal Name
</th>
</tr>
<tr ng-repeat="userPortal in vm.portalsForUser">
<td>
{{userPortal.portal.portalName}}
</td>
<td class="">
<a class="btn btn-primary" ui-sref="goSomewhere({id: userPortal.portal.id})">
Go
</a>
</td>
</tr>
</tbody>
</table>
</div>
bower.json
{
"name": "test",
"description": "just a test",
"main": "index.js",
"authors": [
"me"
],
"license": "ISC",
"homepage": "index.html",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"angular": "^1.5.8",
"angular-ui-router": "ui-router#^0.3.1"
}
}
I added the div ui-view in index.html like suggested by somebody else, but I believe this was already in your initial project.
I also tried to simulate the service like the real one would work (with a promise and with a property data).
Are you sure you have correct versions of ui-router and angular?
There might be an issue with dependency injection. Try this -
resolve: {
portalsForUser: ['userPortalService', '$stateParams', function (userPortalService, $stateParams) {
var userId = $stateParams.id;
return userPortalService.getPortalsForUserPromise(userId)
.then(function (response) {
var userPortals = response.data;
console.log("userPortals", userPortals);
return userPortals;
});
}]
}
Based in your code, I've seen that the your controller it's associated to the module clubSkedApp and your config it's associated to the myApp module.
Use the same module for both, or include the module of your controller like this.
var myApp = angular.module("myApp", ["clubSkedApp","common.services", "ui.router", 'ngMessages']);
Another approach is check why the state it's not loaded.
Ui-router isn't good to raise errors, the only way that i find to check the errors in a route's change is the following:
myApp.run(runFn);
runFn.$inject = ['$rootScope'];
function runFn($rootScope){
//Show the errores caused by the resolve function
$rootScope.$on('$stateChangeError', function (event, toState, toParams,
fromState, fromParams, error) {
event.preventDefault();
console.log(error);
});
}
I know the problem. The solution is very simple.
You need to add <div ui-view></div> into index.html to display your view in the later state like below code.
<body ng-app="myApp" ng-controller="mainCtrl as vm">
<button type="submit" class="btn btn-default" ng-click="vm.clickMe()">
Click Me
</button>
<div ui-view></div>
</body>
For more detail
Check the doc from UI-Router https://angular-ui.github.io/ui-router/
Check an example from my friend:
http://codepen.io/trungk18/pen/EgYyJd
I am trying to consume Web API using AngularJs but getting struck angular side which is hard for me to figure out.
I created HTML, controller and service. Everything seems ok to me but when running the app i get the injection error.
html
<html >
<head>
<title>Motors </title>
<script src="/Scripts/angular.js"></script>
<script src="/Scripts/angular-route.js"></script>
<script src="/View/motorController.js"></script>
</head>
<body ng-app="myApp" ng-controller="motorController">
<div>
<table class="table">
<tr>
<th>Id</th>
<th>Name</th>
<th>Country</th>
</tr>
<tr ng-repeat="m in motors">
<td>{{m.Id}}</td>
<td>{{m.Name}}</td>
<td>{{m.Country}}</td>
</tr>
</table>
</div>
</body>
</html>
AngularJs controller
var module = angular.module('myApp', [])
.controller('motorController', ['$scope', '$motorService',function ($scope, motorService) {
getMotors();
function getMotors() {
motorService.GetAllMotors()
.success(function (motors) {
$scope.motors = motors;
})
.error(function (error) {
$scope.status = 'Unable to load motor data: ' + error.message;
});
}
}]);
angular service
motorApp.factory('motorService', function ($http) {
var urlBase = 'http://localhost:40738/api';
var motorService = {};
motorService.GetAllMotors = function () {
return $http.get(urlBase + '/GetAllMotors');
};
return motorService;
});
Error i am getting on chrmoe browser console
Error: [$injector:unpr] Unknown provider: $motorServiceProvider <- $motorService <- motorController
You have a extra $ infront of MotorService, change
From:
.controller('motorController', ['$scope', '$motorService',function ($scope, motorService)
To:
.controller('motorController', ['$scope', 'motorService',function ($scope, motorService)
The problem with your code is that the factory is given a different module name "motorApp" instead of module name "module".
Use
module.factory('motorService', function ($http) { //change here
var urlBase = 'http://localhost:40738/api';
var motorService = {};
motorService.GetAllMotors = function () {
return $http.get(urlBase + '/GetAllMotors');
};
return motorService;
});
Also in your controller you should remove the "$" from injected service name "motorService"
var module = angular.module('myApp', [])
.controller('motorController', ['$scope', 'motorService',function ($scope, motorService) {
getMotors();
function getMotors() {
motorService.GetAllMotors()
.success(function (motors) {
$scope.motors = motors;
})
.error(function (error) {
$scope.status = 'Unable to load motor data: ' + error.message;
});
}
}]);
I have a simple code here and got stuck in passing the parameter. Here is the code:
route.js
function config($routeProvider) {
$routeProvider
.when('/edit/:id', {
controller: 'UpdateTodoCtrl',
templateUrl: 'app/views/edit-todo.html'
});
}
index.html
<div ng-controller="SomeOtherCtrl">
<table>
<tr ng-repeat="t in todos">
{{ t.name }}
</tr>
</table>
</div
Controller
function UpdateTodoCtrl($http, $scope) {
function init() {
$scope.todos = null;
$scope.loading = true;
$http.get('app/endpoints/edit-todo.php', {
params: { todoId: //how to get the id paramter }
});
}
}
As you can ee in the controller, I commented out the part of my problem. How can I possibly pass the id in my url using $http.get? Thank you.
Your :id is a route parameter so you can do like this :
function UpdateTodoCtrl($http, $scope, $routeParams) {
function init() {
$scope.todos = null;
$scope.loading = true;
$http.get('app/endpoints/edit-todo.php', {
params: { todoId: $routeParams.id }
});
}
}
I am new to angular. I have tried creating an application and all was going well until I decided to create a custom directive.
My html looks like this:
<body ng-app="sapphireApp">
<div class="off-canvas-wrap" data-offcanvas>
<div class="inner-wrap">
<nav class="tab-bar">
<section class="middle tab-bar-section">
<h1 class="title">Sapphire</h1>
</section>
<section class="right-small">
<a class="right-off-canvas-toggle menu-icon" href="#"><span></span></a>
</section>
</nav>
<aside class="right-off-canvas-menu" ng-controller="TopController as topController">
<ul class="off-canvas-list">
<li><label>Users</label></li>
<li ng-hide="topController.userService.isLoggedIn">Login</li>
<li ng-show="topController.userService.isLoggedIn">Logout</li>
</ul>
</aside>
<section class="main-section" ng-view></section>
<a class="exit-off-canvas"></a>
</div>
</div>
<script src="scripts/angular.min.js"></script>
<script src="scripts/mm-foundation/mm-foundation-0.5.1.min.js"></script>
<script src="scripts/angular-cookies.min.js"></script>
<script src="scripts/angular-route.min.js"></script>
<script src="scripts/angular-touch.min.js"></script>
<script src="scripts/app/app.js"></script>
<script src="scripts/app/controllers.js"></script>
<script src="scripts/app/services.js"></script>
<script src="scripts/app/directives.js"></script>
</body>
and my four angularJS files look like this respectively:
app.js
angular.module('sapphireApp', ['ngRoute', 'ngCookies', 'ngTouch', 'mm.foundation'])
.config(function ($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'views/home/index.html'
})
.when('/login', {
templateUrl: 'views/account/login.html'
})
$routeProvider.otherwise({
redirectTo: '/'
});
});
controllers.js
angular.module('sapphireApp')
.controller('TopController', ['UserService',
function (UserService) {
var self = this;
self.userService = UserService;
// Check if the user is logged in when the application
// loads
// User Service will automatically update isLoggedIn
// after this call finishes
UserService.session();
}
])
.controller('HomeController',
function () {
var self = this;
}
)
.controller('LoginController', ['UserService', '$location',
function (UserService, $location) {
var self = this;
self.user = { username: '', password: '' };
self.login = function () {
UserService.login(self.user).then(function (success) {
$location.path('/');
}, function (error) {
self.errorMessage = error.data.msg;
})
};
}
]);
services.js
angular.module('sapphireApp')
.factory('UserService', ['$http', '$cookieStore', function ($http, $cookieStore) {
var service = {
isLoggedIn: false,
session: function () {
var user = $cookieStore.get('user');
if (user)
service.isLoggedIn = true;
return user;
},
login: function (user) {
return $http.post('/api/account/login', user)
.then(function (response) {
service.isLoggedIn = true;
$cookieStore.put('user', response);
return response;
});
}
};
return service;
}]);
directives.js
angular.module('sapphireApp')
.directive('square', function () {
return {
restrict: 'E',
template: '<div class="square"><h1>Show something else</h1></div>',
link: function () {
alert("this is working");
}
};
});
The login view works fine, but the home view doesn't. It looks like this:
<div class="row" ng-controller="HomeController as homeController">
<div class="small-2 columns">
<sqaure>
<h1>This is the square</h1>
</sqaure>
</div>
</div>
Now, because I have created the directive square and set it to be an element, I would expect an output like this:
<sqaure>
<div class="square">
<h1>Show something else</h1>
</div>
</sqaure>
and I would also expect there to be an alert. But I get nothing. No errors and the Html stays unmodified.
Can anyone tell me why? I assume because I am getting no errors, it is just a misunderstanding on my part.
You have a typo in the directive:
<sqaure> //typo here
<h1>This is the square</h1>
</sqaure> //typo here
Change sqaure to square.
I'm working on building a little app that accepts input from a form (the input being a name) and then goes on to POST the name to a mock webservice using $httpBackend. After the POST I then do a GET also from a mock webservice using $httpBackend that then gets the name/variable that was set with the POST. After getting it from the service a simple greeting is constructed and displayed back at the client.
However, currently when the data gets displayed now back to the client it reads "Hello undefined!" When it should be reading "Hello [whatever name you inputed] !". I used Yeoman to do my app scaffolding so I hope everyone will be able to understand my file and directory structure.
My app.js:
'use strict';
angular
.module('sayHiApp', [
'ngCookies',
'ngMockE2E',
'ngResource',
'ngSanitize',
'ngRoute'
])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.otherwise({
redirectTo: '/'
});
})
.run(function($httpBackend) {
var name = 'Default Name';
$httpBackend.whenPOST('/name').respond(function(method, url, data) {
//name = angular.fromJson(data);
name = data;
return [200, name, {}];
});
$httpBackend.whenGET('/name').respond(name);
// Tell httpBackend to ignore GET requests to our templates
$httpBackend.whenGET(/\.html$/).passThrough();
});
My main.js:
'use strict';
angular.module('sayHiApp')
.controller('MainCtrl', function ($scope, $http) {
// Accepts form input
$scope.submit = function() {
// POSTS data to webservice
setName($scope.input);
// GET data from webservice
var name = getName();
// Construct greeting
$scope.greeting = 'Hello ' + name + ' !';
};
function setName (dataToPost) {
$http.post('/name', dataToPost).
success(function(data) {
$scope.error = false;
return data;
}).
error(function(data) {
$scope.error = true;
return data;
});
}
// GET name from webservice
function getName () {
$http.get('/name').
success(function(data) {
$scope.error = false;
return data;
}).
error(function(data) {
$scope.error = true;
return data;
});
}
});
My main.html:
<div class="row text-center">
<div class="col-xs-12 col-md-6 col-md-offset-3">
<img src="../images/SayHi.png" class="logo" />
</div>
</div>
<div class="row text-center">
<div class="col-xs-10 col-xs-offset-1 col-md-4 col-md-offset-4">
<form role="form" name="greeting-form" ng-Submit="submit()">
<input type="text" class="form-control input-field" name="name-field" placeholder="Your Name" ng-model="input">
<button type="submit" class="btn btn-default button">Greet Me!</button>
</form>
</div>
</div>
<div class="row text-center">
<div class="col-xs-12 col-md-6 col-md-offset-3">
<p class="greeting">{{greeting}}</p>
</div>
</div>
At the moment your getName() method returns nothing. Also you cant just call getName() and expect the result to be available immediately after the function call since $http.get() runs asynchronously.
You should try something like this:
function getName () {
//return the Promise
return $http.get('/name').success(function(data) {
$scope.error = false;
return data;
}).error(function(data) {
$scope.error = true;
return data;
});
}
$scope.submit = function() {
setName($scope.input);
//wait for the Promise to be resolved and then update the view
getName().then(function(name) {
$scope.greeting = 'Hello ' + name + ' !';
});
};
By the way you should put getName(), setName() into a service.
You can't return a regular variable from an async call because by the time this success block is excuted the function already finished it's iteration.
You need to return a promise object (as a guide line, and preffered do it from a service).
I won't fix your code but I'll share the necessary tool with you - Promises.
Following angular's doc for $q and $http you can build yourself a template for async calls handling.
The template should be something like that:
angular.module('mymodule').factory('MyAsyncService', function($q, http) {
var service = {
getNames: function() {
var params ={};
var deferObject = $q.defer();
params.nameId = 1;
$http.get('/names', params).success(function(data) {
deferObject.resolve(data)
}).error(function(error) {
deferObject.reject(error)
});
return $q.promise;
}
}
});
angular.module('mymodule').controller('MyGettingNameCtrl', ['$scope', 'MyAsyncService', function ($scope, MyAsyncService) {
$scope.getName = function() {
MyAsyncService.getName().then(function(data) {
//do something with name
}, function(error) {
//Error
})
}
}]);