In my angularjs code below why is the IsLoggedIn and Username not available to the view. Not sure what's wrong, any help will be highly appreciated:
'use strict';
myApp.controller('masterPageController',
function masterPageController($scope, loginService, stateService) {
$scope.State = stateService.State;
});
myApp.factory('stateService', function () {
// todo: fetch the state from server when the service is initialised
var state = {};
return {
State: state,
};
});
myApp.factory('loginService', function ($http, $q, stateService) {
return {
Login: function (logindetails) {
var deferred = $q.defer();
$http({ method: 'POST', url: '/api/Login/Login', data: JSON.stringify(logindetails), headers: { 'Content-Type': 'application/json' } }).
success(function (data, status, headers, config) {
stateService.State = data.State;
deferred.resolve(data);
}).
error(function (data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
}
};
});
<div ng-controller="masterPageController">
<div>
<div>
<div>
<a href="/logout" ng-show="State.IsLoggedIn" >{{ State.Username }}</a>
</div>
</div>
</div>
</div>
EDIT: It doesn't work when I set the stateService.State property in my loginService
Change the way you build the service from "factory" to "service" and define "state" on this and do not return anything.
myApp.service('stateService', function () {
// todo: fetch the state from server when the service is initialised
this.state = {};
});
http://codepen.io/rotempe4/pen/KNMpzZ
Related
I'm trying to write down a Controller that pass a var to a Factory in Angularjs.. The following code return (in console) the values, but I'm not been able to load that into my html page.
Just to record, yes, I'm starting in angularjs.
app.js
var myApp = angular.module('myApp',[]);
myApp.factory('eventData', function ($http, $q) {
delete $http.defaults.headers.common['X-Requested-With'];
return {
getEvent: function (id) {
var deferred = $q.defer();
$http({
method: 'GET',
url: 'page' + id
}).
success(function (data, status, headers, config) {
deferred.resolve(data);
}).
error(function (data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
}
};
});
myApp.controller('AngularJSCtrl',
function FeederController($scope, eventData) {
$scope.data = [];
for (var i = 0; i < 10; i++) {
eventData.getEvent(i).then(
function (data) {
$scope.data = data;
console.log($scope.data);
},
function (statusCode) {
console.log(statusCode)
});
}
}
);
page.html
<div ng-controller="AngularJSCtrl">
<div ng-repeat="patient in patients">
<businesscard>{{patient.name}}</businesscard>
</div>
</div>
Problem solved. I've searched for a while until get this right.
Thanks for #Claies and Brad Barrow for the tips :)
app.js
var myApp = angular.module('myApp',[]);
myApp.factory('patientsData', function ($http) {
delete $http.defaults.headers.common['X-Requested-With'];
return {
getPatients: function () {
return $http({
url: 'http://localhost/ucamradio/php/tst.php?campusId=1',
method: 'GET'
})
}
}
});
myApp.controller('AngularJSCtrl', function($scope, patientsData){
$scope.patients = [];
var handleSuccess = function(data, status) {
//$scope.patients = data;
$scope.patients.push(data);
console.log($scope.patients);
};
patientsData.getPatients().success(handleSuccess);
});
page.html
<div ng-controller="AngularJSCtrl">
<div ng-repeat="patient in patients">
<businesscard>{{patient.name}}</businesscard>
</div>
<!--
<div ng-repeat="patient in patients ">
<businesscard>{{patient.id}}</businesscard>
</div> -->
</div>
I am trying to set value in html page from angularjs controller.
I am getting value from web api in service but I have issue that I am always getting error:
TypeError: Cannot set property 'messageFromServer' of undefined
But I can't figure what am I doing wrong here. What am I missing?
On the html part I have:
<div ng-app="myApp" ng-controller="AngularController">
<p>{{messageFromServer}}</p>
</div>
In the controller I have:
var app = angular.module('myApp', []);
app.controller('AngularController', ['$scope', 'messageService', function ($scope, messageService) {
$scope.messageFromServer = "When I set it here it works!"
messageService.getMessage();
}]);
app.service('messageService', ['$http', function ($http) {
this.getMessage = function ($scope) {
return $http({
method: "GET",
url: "api/GetMessage",
headers: { 'Content-Type': 'application/json' }
}).success(function (data) {
$scope.messageFromServer = data;
console.log(data);
}).error(function (data) {
console.log(data);
})
};
}]);
Basically the problem is, you missed to $scope object to the service getMessage method. But this is not a good approach to go with. As service is singleton object, it shouldn't manipulate scope directly by passing $scope to it. Rather than make it as generic as possible and do return data from there.
Instead return promise/data from a service and then assign data to the scope from the controller .then function.
app.service('messageService', ['$http', function ($http) {
this.getMessage = function () {
return $http({
method: "GET",
url: "api/GetMessage",
headers: { 'Content-Type': 'application/json' }
}).then(function (response) {
//you could have do some data validation here
//on the basis of that data could be returned to the consumer method
//consumer method will have access only to the data of the request
//other information about request is hidden to consumer method like headers, status, etc.
console.log(response.data);
return response.data;
}, function (error) {
return error;
})
};
}]);
Controller
app.controller('AngularController', ['$scope', 'messageService',
function ($scope, messageService) {
$scope.messageFromServer = "When I set it here it works!"
messageService.getMessage().then(function(data){
$scope.messageFromServer = data;
});
}
]);
Don't use $scope in your service, just return the promise from $http.
var app = angular.module('myApp', []);
app.service('messageService', ['$http', function ($http) {
this.getMessage = function () {
return $http({
method: "GET",
url: "api/GetMessage",
headers: { 'Content-Type': 'application/json' }
});
};
}]);
app.controller('AngularController', ['$scope', 'messageService', function ($scope, messageService) {
messageService.getMessage().then(function(data) {
$scope.messageFromServer = data;
});
}]);
In this example you can unwrap the promise in your controller, or even better you can use the router to resolve the promise and have it injected into your controller.
app.config(function($routeProvider) {
$routeProvider.when('/',{
controller: 'AngularController',
templateUrl: 'views/view.html',
resolve: {
message: function(messageService) {
return messageService.getMessage();
}
}
});
});
Then in your AngularController, you'll have an unwrapped promise:
app.controller('AngularController', ['$scope', 'message', function ($scope, message) {
$scope.messageFromServer = message;
}]);
when I submit a form I have a controller that communicates with a service, which gets data from a server and return these data to the controller. Meanwhile, I change view with the form action. My problem is that I'd need the server response data in the second view (which has an another controller), but these are undefined. How can I fix this problem?
Ps. I'm sorry for my English
// code...
.state('app.search', {
url: "/search",
views: {
'menuContent' :{
templateUrl: "templates/search.html",
controller: 'SearchCtrl'
}
}
})
.state('app.result', {
url: "/result",
views: {
'menuContent' :{
templateUrl: "templates/result.html",
controller: "ResultCtrl",
}
}
})
// code...
<form name="search_form" ng-submit="searchLines()" action="#/app/result" novalidate>
// code...
</form>
.factory('Bus', function($http){
return{
get: function(callback){
$http({
method: "POST",
url: "someUrl",
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: {someData from the form}
})
.success(function(data) {
callback(data);
})
.error(function(data, status, error) {
console.log(data, status, error);
});
}
}
});
.controller('SearchCtrl', function($scope, Bus){
$scope.searchLines = function(){
Bus.get(function(data){
$scope.company = data.company; // this is ok
});
};
})
.controller('ResultCtrl', function($scope, Bus){
// I'd like to have $scope.company here
})
Use a service for that.
Controllers shouldn't hold state.
Two controllers can communicate via a service(the service will hold the state as well).
Add a company variable on the Bus service and add a getter so other controllers can fetch the data from Bus.
Example:
HTML:
<div ng-app="app">
<div ng-controller="aCtrl">{{model.stateA}}</div>
<div ng-controller="bCtrl">{{model.stateB}}</div>
</div>
JS:
var app = angular.module('app', []);
app.service('myService', function ($q) {
var state = "12312";
this.getStateFromServer = function () {
return $q.when(state);
}
this.getRealState = function(){
return state;
};
});
app.controller('aCtrl', function ($scope, myService) {
myService.getStateFromServer().then(function (res) {
$scope.model = {
stateA: "A" + myService.getRealState()
};
});
});
app.controller('bCtrl', function ($scope, myService) {
$scope.model = {stateB: "B" + myService.getRealState()};
});
JSFIDDLE.
I'm not quite sure what I'm doing wrong, but it seems that my profile doesn't resolve by the time we get to the MainCtrl. The user however does, resolve. Am I, perhaps not fetching the profile information properly in the Auth Service?
Router:
angular.module('app')
.config(function ($stateProvide) {
$stateProvider
.state('main', {
url: '/main',
templateUrl: 'app/main/main',
controller: 'MainCtrl',
resolve: {
user: function (Auth) {
return Auth.getUser();
},
profile: function (user) {
return Auth.getProfile();
}
}
});
});
Controller:
angular.module('app')
.controller('MainCtrl', function ($scope, user, profile) {
$scope.user = user;
$scope.profile = profile; <- DOESNT RESOLVE
});
Auth Service:
angular.module('app')
.factory('Auth', function ($firebaseSimpleLogin, $firebase, FBURL) {
var ref = new Firebase(FBURL);
var auth = $firebaseSimpleLogin(ref);
var Auth = {
user: {},
getUser: function () {
return auth.$getCurrentUser();
},
getProfile: function(uid) {
return $firebase(ref.child('users').child(uid)).$asObject();
}
};
return Auth;
});
Something like
auth.$getCurrentUser()
returns a promise so you need a
.then(function(user) {
event before your callback complete
In your case you may just resolve on the then, something like
Auth.getUser().then(function(user){ return user; });
Also $asObject() needs $loaded() for it's promise
var obj = $firebase(ref).$asObject();
obj.$loaded()
.then(function(data) {})
Try this structure for your promises:
var fetchSomething = function (action, params) {
var promise = $http({
method: 'POST',
url: 'someurl to the firebase',
data: params,
headers: {
'Access-Control-Allow-Origin': true,
'Content-Type': 'application/json'
}
}).success(function (data, status, headers, config) {
return data;
});
return promise;
};
I'm trying to write an Angular service and it seems like there is something missing. My problem is its not returning any value to my Angular controller
getPrepTimes() method is not returning the http data
But when I check the network (via Chrome dev tools) it will correctly call the external api and return a json object as a response
#my service
'use strict';
angular.module('recipeapp')
.service('prepTimeService',['$http', function($http){
this.prepTime = getPrepTimes();
function getPrepTimes(){
$http({
url: '/prep_times/index.json',
method: 'GET'
})
.success(function (data, status, header, config){
return data;
});
};
}
]);
#controller
'use strict';
angular.module('recipeapp')
.controller('recipeCtrl', ['$scope', 'prepTimeService', function($scope, prepTimeService){
$scope.prep_time = prepTimeService.prepTime;
}]);
When I checked the method getPrepTimes() with returning a string it works. What could be missing here?
A couple things are wrong with the above. You assign this.prepTime to getPrepTimes(). The () there will invoke getPrepTimes immediately, and not when you actually call it! You also need to utilize callbacks to get your data back and use it:
angular.module('recipeapp').service('prepTimeService',['$http', function($http){
this.prepTime = getPrepTimes;
function getPrepTimes(callback) {
$http({
url: '/prep_times/index.json',
method: 'GET'
}).success(function (data, status, header, config){
callback(data);
});
};
}]);
And now use it like so:
prepTimeService.prepTime(function(data) {
$scope.prep_time = data;
});
Calls to the $http service are async, which means you need to return a promise (and not a value):
this.prepTime = function() {
return $http({
url: '/prep_times/index.json',
method: 'GET'
});
};
And on the controller:
angular.module('recipeapp')
.controller('recipeCtrl', ['$scope', 'prepTimeService', function($scope, prepTimeService){
$scope.prep_time = prepTimeService.prepTime()
.success(function (data, status, header, config){
$scope.someVar = data;
});
}]);
Wrap answer with promise:
var self = this;
var deferred = $q.defer();
self.getPrepTimes = function() {
$http({
url: '/prep_times/index.json',
method: 'GET'
})
.success(function(data, status, headers, config) {
if (data.error === undefined) {
deferred.resolve(data);
} else {
if (data.error !== undefined) {
} else {
deferred.reject(data);
}
}
}).error(function(data, status, headers, config) {
deferred.reject(data);
});
return deferred.promise;
};
In controller call it:
prepTimeService.getPrepTimes().then(function(result) {
$scope.prep_time = result;
},
function(error) {
// show alert
});