angular ui-router nested resolves are not resolving - angularjs

I have nested ui-views which are both waiting on data from http request. In the following code i have simulated this with timeouts. If i set the timeouts any longer than 10 ms then my plunker wont load at all.
var myapp = angular.module('myapp', ["ui.router"])
myapp.config(function($stateProvider, $urlRouterProvider){
// For any unmatched url, send to /route1
$urlRouterProvider.otherwise("/route1")
try{
$stateProvider
.state('contacts', {
templateUrl: 'contacts.html',
controller: function($scope, service1){
$scope.title = service1.getData()
}
,resolve:{
titlePromise:function(service1){
return service1.myPromise
}}
})
.state('contacts.list', {
templateUrl: 'contacts.list.html',
controller: function($scope, service2){
$scope.contacts = service2.getData();
},
resolve:{
contactPromise:function(service2){return service2.myPromise}
}
});
}catch(e){
alert.log(e);
}
});
The services are defined as follows.
myapp.factory('service1',['$q', function($q){
var title = 'Not Yet';
var _promise = $q.defer();
setTimeout(function(){
title='My Contacts';
_promise.resolve(true);
},100);
return {
getData:function(){return title},
myPromise: _promise.promise
}
}]);
myapp.factory('service2',['$q','service1', function($q, service1){
var data = [];
var _promise = $q.defer();
setTimeout(function(){
service1.myPromise.then(function(){
data=[{ name: 'Alice' }, { name: 'Bob' }];
_promise.resolve(true);
})
},100);
return{
getData:function(){return data},
myPromise:_promise
}
}]);
I need service2 to wait until service 1 returns its data in order to fulfill its request.The way I have it set up does not seem to work. What have I done wrong? If there is a better way to set up my app any suggestions are appreciated. I have modified the ui-view nested view demo plunker her: plnkr

Have a read of how hierarchical resolves work:
https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views#wiki-what-do-child-states-inherit-from-parent-states
You don't need to wait for service 1 to complete inside service 2, but rather inject the results from the parent resolve into the child resolve function.

Related

Wait for $http result before initializing angular app

I have an angular app that needs to do a quick http request to get some config information before the rest of the application is initiated, at least before the controllers. Looked into using $UrlRouterProvider, but I did not figure out how to make the app wait for the http be done.
What I need to be finished:
$http({method: 'GET', url: '/config'}).then(function(res) {
configProvider.setConfig(res.data.config);
}
You can create a separate js file where you can make http request and then initialize/bootstrap your app via js code instead of ng-app in html code.
Refer the below code:
(function() {
var application, bootstrapApplication, fetchData;
application = angular.module('app');
fetchData = function() {
var $http, initInjector;
initInjector = angular.injector(['ng']);
$http = initInjector.get('$http');
$http.get('<url>');
};
bootstrapApplication = function() {
angular.element(document).ready(function() {
angular.bootstrap(document, ['app']);
});
};
fetchData().then(bootstrapApplication);
})();
I hope it helps.
Resolve must be declared on state, not on the view
change
.state('app', {
abstract: true,
url:'/',
views: {
"content": {
templateUrl: "myurl.html"
},
resolve {
myVar: ['$http', 'myService', function($http, myService) {
return $http({method: 'GET', url:'url'})
.then(function(res) { //do stuff })
to
.state('app', {
abstract: true,
url:'/',
views: {
"content": {
templateUrl: "myurl.html"
}
},
resolve {
myVar: ['$http', 'myService', function($http, myService) {
return $http({method: 'GET', url:'url'})
.then(function(res) { //do stuff })...

inject service[declared in separate file] in app.config or use it in a controller

I am trying to use the code from here to show routes only when a promise is TRUE
I am following this for my directory structure
app
- Orders
-orders.html
-OrderController.js
-OrderService.js
Main-Config [app.js]
var myApp = angular.module('myApp', ['ngRoute','ngAnimate','ui.bootstrap','myApp.OrderController']);
myApp.config(function($routeProvider, $locationProvider){
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
$routeProvider
.when('/orders', {
templateUrl: 'orders/orders.html',
controller: 'OrderController',
resolve:{
customerExpenses: function(OrderService){
return OrderService.getOrders($route.current.params.customerName);
}
}
})
})
OrderService.js
angular.module('myApp').factory('OrderService', ['$http', function($http) {
var sdo = {
getNames: function() {
var promise = $http({
method: 'GET',
url: ''
});
promise.success(function(data, status, headers, conf) {
return data;
});
return promise;
}
}
return sdo;
}]);
I have tried the Accepted answer from here, and one of the suggestion from another SO article
angular.module('myApp')
.service('FooService', function(){
//...etc
})
.config(function(FooServiceProvider){
//...etc
});
As I have my service in a different file, I am trying to determine if I can use it in app.js file without using provider or is that the only way to use service in app.config?
UPDATE 1:
If i want to use the service in a controller
angular.module('myApp.OrderController',[]).controller('OrderController', function ($scope) {
$scope.displayed=[];
$scope.displayed.push(OrderService.getNames());
});
I get OrderService not available
Have tried this:
angular.module('myApp.OrderController',[]).controller('OrderController', ['$scope','OrderService',function ($scope) {
$scope.displayed=[];
$scope.displayed.push(OrderService.getNames());
}]);
followed example :
angular.
module('myServiceModule', []).
controller('MyController', ['$scope','notify', function ($scope, notify) {
$scope.callNotify = function(msg) {
notify(msg);
};
}]).
factory('notify', ['$window', function(win) {
var msgs = [];
return function(msg) {
msgs.push(msg);
if (msgs.length == 3) {
win.alert(msgs.join("\n"));
msgs = [];
}
};
}]);
but can not use my service. my controller and service are in different files
I added this question here as I feel they are somewaht related.
You have not injected your service OrderService, change your code in very first line
var myApp = angular.module('myApp', ['ngRoute','ngAnimate', ....'OrderService'])
myApp.config(function($routeProvider, $locationProvider, OrderService){
....
})
Rest of the code looks good

AngularJS - Save data to $scope using routes?

i am just learning basics of angular and today it started to change my app using a factory to get data and implementing route provider ! So far everything works fine! But when I try to add data on another view and head back to my list view scope is reloaded again from factory and no added data shows up.
My approach won't work because each time change my view I will call my controller which reloads data from factory! What can I do to make my Add template will work and changes data everywhere else too.
Maybe somebody can give me a tip how to cope with this problem ?
script.js
var app = angular.module('printTrips', ['ngRoute']);
app.factory('tripFactory', function($http) {
return{
getTrips : function() {
return $http({
url: 'trips.json',
method: 'GET'
})
}
}
});
app.controller('TripController', function($scope, $filter, tripFactory) {
$scope.trips = [];
tripFactory.getTrips().success(function(data){
$scope.trips=data;
var orderBy = $filter('orderBy');
$scope.order = function(predicate, reverse) {
$scope.trips = orderBy($scope.trips, predicate, reverse)};
$scope.addTrip = function(){
$scope.trips.push({'Startdate':$scope.newdate, DAYS: [{"DATE":$scope.newdate,"IATA":$scope.newiata,"DUTY":$scope.newduty}]})
$scope.order('Startdate',false)
$scope.newdate = ''
$scope.newiata = ''
$scope.newduty = ''
}
$scope.deleteTrip = function(index){
$scope.trips.splice(index, 1);
}
});
});
view.js
app.config(function ($routeProvider){
$routeProvider
.when('/',
{
controller: 'TripController',
templateUrl: 'view1.html'
})
.when('/view1',
{
controller: 'TripController',
templateUrl: 'view1.html'
})
.when('/view2',
{
controller: 'TripController',
templateUrl: 'view2.html'
})
.when('/addtrip',
{
controller: 'TripController',
templateUrl: 'add_trip.html'
})
.otherwise({ redirectTo: 'View1.html'});
});
Here is my plunker
Thanks for your help
You should use Service instead of Factory.
Services are loaded each time they are called. Factory are just loaded once.
app.service('tripFactory', function($http) {
return{
getTrips : function() {
return $http({
url: 'trips.json',
method: 'GET'
})
}
}
});

How to avoid asynchronous processing in angular js

I'm new in angular js . I want to do authentication . I've to direct to some pages only after checking authentication. I've checkLogin function for that. While calling that checkLogin function it take some processing time. If true it redirects corresponding page. If false it remains the same page. But while calling the checkLogin function the same time it process the app.config function concurrently. I need to to block it. I've to process that only after chcklogin.
var app = angular.module('myApp', ['ngRoute', 'ngResource','ngCsv', 'ui', 'ngSanitize', 'ngQuickDate', 'ui.tree', 'blueimp.fileupload','mentio']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'app/views/login.html',
controller: 'LoginController',
title: 'Login'
}).when('/signup', {
templateUrl: 'app/views/signup.html',
controller: 'SignUpController',
title: 'Sign Up'
}).when('/dashboard', {
templateUrl: 'app/views/dashboard.html',
controller: 'DashboardController',
title: 'Dashboard'});});
app.run(function($rootScope, $location, DataService) {
var unAuthenticatedPages = ["/", "/signup"];
var checkLogin = function() {
if (!$rootScope.isLoggedIn && unAuthenticatedPages.indexOf($location.path()) === -1) {
$location.path('/');
}
};
$rootScope.isLoggedIn = true;
DataService.getUserListById(1, function(user) {
$rootScope.user = user;
});
$rootScope.$on('$locationChangeStart', checkLogin);});
angularjs comes with a built in promise library $q which can be injected and used something like this:
var doSomething = function() {
var deferred = $q.defer();
//do someething here, when you're ready resolve the deferred object
deferred.resolve();
//this won't execute until deferred is resolved or rejected
return deferred.promise;
};
You can also return variables with your promise if required. You can then
doSomething().then(function() {
//this executes if the promise is resolved
}, function() {
//this executes if the promise is rejected
});

$http service executing multiple times in controller

I am using $http service to call server that return json data.howerver each time i request for the json data , the $http service is executing multiple times.dont know what went wrong.plz help. thanks in advance.below is my code.
var app = angular.module('Demo',[]);
app.config(function ($routeProvider) {
$routeProvider
.when('/users',
{
templateUrl: "users.html",
controller: "users"
}
).when('/users/new',
{
templateUrl: 'new.html',
controller : 'newuser'
}).when('/users/:id/edit',
{
templateUrl: 'edit.html',
controller: 'edit'
})
});
app.controller('users',function($scope,$http){
$scope.list_of_users = [];
$http.get('http://testing.com:3000 /users.json').success(function(data,status,header,config){
angular.copy(data,$scope.list_of_users)
})
});
app.controller('newuser',function($scope,$http,$location){
$scope.done = function(){
var data = {user: {name: $scope.name}};
$http.post("http://testing.com:3000/users.json",data).success(function(data,status,header,config){
$location.path('/users');
}).error(function(data,stauts,header,confi){
});
};
});
app.controller('edit',function($scope,$http,$routeParams,$location){
$scope.name="";
$http.get("http://testing.com/users/"+$routeParams.id +".json").success(function(data,status,header,config){
console.log(data);
$scope.name = data['user']['name'];
});
$scope.update = function(){
var data = {user: {name: $scope.name}};
$http.put('http://localhost:3000/users/$routeParams.id',data).success(function(data,status,header,config){
$location.path("/users");
}).error(function(data,status,header,config){
});
}
});
Most likly you defined your controller in both the routeProvider and in the actuall template ( ng-controller ). This makes it run multiple times. Remove one of them and try again.

Resources