I'm wondering how I can route to a different view when I'm working with this Pubnub function here.
QueueController
Pubnub.hereNow(
{
includeUUIDs: true,
includeState: true
},
function (status, response){
console.log(response);
//do some algorithm with response
$location.path('/chat');
}
);
So basically I'm getting the response from this hereNow function and then when the algorithm passes a condition inside, I want it to go from my QueueController to my ChatController so the users can begin chatting! I even removed the algorithm from the function and had the route just by itself, but it doesn't work at all.
When I put the $location.path('/chat') outside of my hereNow function, it does route very nicely.
So how does one route to a different view in this case?
Just discovered this answer and it seems to be working!
Pubnub.hereNow(
{
includeUUIDs: true,
includeState: true
},
function (status, response){
console.log(response);
$rootScope.$apply(function(){
$location.path('/chat');
});
}
);
I added the $rootScope as a dependency in my QueueController
app.controller('QueueController', ['$scope', '$location', '$rootScope', 'languageService', 'Pubnub',
function($scope, $location, $rootScope, languageService, Pubnub){ ... }]);
Related
So I am trying to figure out the easiest route for authentication with AngularJS and Google Plus. I have worked with angular-google-plus and it is great, spits back all my user information. I Then wanted to get back if a user is registered or not when they come to a new page or controller in my project. So I found this post which basically said the project needs to extend the api. Fine, but he implements a watcher that, when executed in my Controller works for the gapi, but when it checks for the gapi.auth it returns undefined. My console.log tells me both of them are there and are objects. Here is my controller code:
.controller('LoginController', ['$scope', '$state', '$window', '$http','$rootScope', 'GooglePlus', function ($scope, $state, $window, $http, $rootScope, GooglePlus) {
var checkGoogleReady = $rootScope.$watch(function() {
console.log(gapi);
$scope.login = function() {
GooglePlus.login().then(function (authResult) {
console.log(authResult);
GooglePlus.getUser().then(function (user) {
console.log(user);
});
}, function (err) {
console.log(err);
});
};
}])
So the stuff inside the login() function all works, returns everything I need. But outside it, it fails to get gapi.auth and never changes after that. I feel like it checks, finds gapi, then changes gapi.auth and then tries to wait for another change, never getting the gapi.auth. Here is a picture of the console:
So you can see all 3 objects actually have the auth property on them. So I am not sure why the gapi.auth is coming back undefined.
I have seen an example that uses MVC. It has a return URL which comes up with a screen that is called from the email sent out. But I have an SPA AngularJS application so it is a bit different. Has anyone tried to do this with a SPA and if so how did they go about implementing it. Any pointers would be much appreciated.
I'm working on the same now; needs more work to make it pretty and whatnot, but hopefully you get the general idea.
The confirmation URL looks like:
http://localhost:8000/app.html#/confirm/9a28aa89e84e80153b1f2083d38911acbae12e8365dd13c83cee55f79481e1f8
(localhost:8000 because I'm testing). I then have a route for ui-router:
var confirm = {
name: 'confirm',
url: '/confirm/:auth',
templateUrl: 'app/front/partial/confirm.html',
params: {auth: {}}
} ;
$stateProvider.state(confirm) ;
the confirm.html partial (which obviously needs fleshing out a bit!) is:
<div ng-controller="Fapi.Front.Confirm.Ctrl">
CONFIRM
</div>
and the controller is:
angular.module('myApp')
.controller('App.Front.Confirm.Ctrl', [
'$scope', '$state', '$stateParams', 'toaster', 'MyDataService',
function ($scope, $state, $stateParams, toaster, MyDataService) {
MyDataService.confirm (
{auth: $stateParams.auth},
function (data) {
toaster.pop('success', 'Your registration has been confirmed') ;
setTimeout(function () { $state.go('login') }, 5000) ;
},
function (data) {
toaster.pop('error', data.message) ;
}
)
}]) ;
MyDataService is just a service that wraps $http calls to the server.
So, instead of the 'usual' situation where the URL invokes a script on the server which does the work, and then renders a 'you have been confirmed' (or not) page, here the router takes the browser to a page that then makes an AJAX call to the server to do the confirmation.
I'm looking for a way to pass a value to my controller from my appRoutes. With the idea for it to call a function and do some magic. heres some code so you get an idea:
appRoutes.js
$routeProvider
.when('/students/some/path/:id', {
templateUrl: 'views/studentRecord.html',
controller: 'StudentsController',
resolve: { myVar: 'test' }
});
studentsCtrl.js
angular.module('StudentsCtrl', [])
.controller('StudentsController', function($scope, $http, $routeParams,
$location, myVar, Students) {
/* ... */
});
Ideally, I'd like to call a given function within this controller - but parsing a value would be just as good. The idea is that the controller handles all pages to do with 'students' and will make some http calls so my node server will do some calls to mongodb. Ive tried a few variations on the internet and with no luck. I got an error:
Error: $injector:unpr Unknown Provider
but I'm not sure how to resolve it.
EDIT: I've half resolved this now by using this; http://plnkr.co/edit/mSb58e8cGDNYU27xSizk?p=preview
ideally i'd like to separate the app.js into controllers and services - currently working on this, any edit of the plnkr would be great.
Question still stands of is it possible to hit a function within the controller first, rather than resolving one through a service?
In each resolve property, you can have a function that lets Angular inject services for you to use:
resolve: {
myVar1: function(testService) { return testService.fetchList1(); },
myVar2: function(anotherService, $http) {
// call service functions to mongo-db or what have you
return result;
}
}
Then, your controller, just inject the properties:
// myVar1 and myVar2 are now here
app.controller('StudentsController', function($scope, myVar1, myVar2) {
/* ... */
});
If the returned value from the function inside resolve is a promise, then it will be resolved before controller code is called (hence, the name resolve). This is actually the recommended approach as it makes service code (such as testService) reusable across many controllers.
Passing a function that returns the value
.state('tab2', {
url: '/tab2',
templateUrl: 'templates/tab2.html',
controller: 'Tab2Controller as tab2Ctrl',
//promise
resolve: {
lastName: function () { return 'makarov'}
}
});
Then in the controller
function Tab2Controller(lastName) {
console.log("Tab2", lastName);
}
I am relatively new to Angular but I am quite an experienced developer. So far I have made quite some progress in building my application to work with a CMS. I am a bit lost however on what the 'correct' approach would be to handle data in my model.
This is best described with an example:
Because I am hooking up my angular frontend with a CMS, the routing (pages) exist only in the CMS context. This means that the routing should be dynamic as well. I have managed to get the dynamic routes thing to work, but when I try to do things the right way (actually getting data from a server) I run into some issues...
app.config(function($provide, $routeProvider) {
$provide.factory("$routeProvider", function() {
return $routeProvider;
});
});
// Load the dynamic routes from the API...
app.run(function($routeProvider, $http, $scope, logger, siteRoutes) {
$routeProvider.when('/', { templateUrl: '__views/', controller: 'ContentPageController' });
$routeProvider.otherwise({redirectTo: '/'});
});
In other words, I inject a service into my app.run method (siteRoutes) and this one should connect to the API.
So my siteRoutes is a service:
cmsModule.service('siteRoutes', function siteRouteFactory(apiConnection, logger)
// SNIP
And in this service I inject my generic apiConnection service:
cmsModule.factory('apiConnection', ['$q', '$http', '$timeout', 'logger', function apiConnectionService($q, $http, $timeout, logger)
What I want is this:
I would like the siteRoutes service to load the data once and not execute the connection every time. I did this in the following way:
bla.service('example', function() {
var service = {
get: function(apiStuff) { // DO API CONNECT WITH .THEN HERE },
data: {}
}
service.get();
return service;
}
I would like one entry point towards the Api that handles all the $q stuff (my factory) I assumed I need to handle all the .then() stuff in my siteRoutes object, which is what I did.
Now, what happens in my app.run method is that I don't get the siteRoutes object with any data. So I recon I need to do a .then there as well?
But that made me question the entire design of putting all logic in a separate factory for the connection, because I basically like my app to just use the data and have my library deal with the async stuff (if you get what I am saying)...
Hope this is clear.
TL;DR -> How to make your services / factories handle async stuff without making your 'app' deal with it?
The templateUrl property can also be a function that takes the url parametes as input.
In the example below all routes will load a template with same name.
Eg. domain.com/#/blabla.html will load the view blabla.html from the server.
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/:templateName',
{
templateUrl: function (params) {
return params.templateName + ".html";
}
}
)
.otherwise({ redirectTo: '/main' });
}]);
I have a SPA Angular app which has two main html divs. One of these changes frequently and the other less frequently. The frequently changing one uses $route in the app.config. The less frequently changing div also needs to be aware of url changes, so I want to listen for changes in $routeParamas and do stuff accordingly.
So in my controller I have:
.controller('SecondaryCtrl', function ($scope, $routeParams, MyService) {
$scope.$watch('routeParams', function () {
console.log('routeParams: ', $routeParams);
// I need $routeParams.projectId to compose an API call.
});
...
});
In the console, $routeParams is returned as an empty object. I know that if the Controller and route are defined in the app.config, the$routeParams are available, but the app.config already has definition for the given route which links to the PrimaryCtrl:
.config( function ($interpolateProvider, $routeProvider) {
$routeProvider
.when('/project/:projectId', {
templateUrl : 'partials/_project_detail.html',
controller: 'PrimaryCtrl',
resolve: {
project: function ($route, MyService) {
return MyService.get('projects/', $route.current.params.projectId);
},
}
})
So, how can I get access to the $routeParams in my SecondaryCtrl when $routeParams changes?
You can listen to the $routeChangeSuccess event inside of watching $routeParams, like this:
.controller('SecondaryCtrl', function ($scope, MyService) {
$scope.$on('$routeChangeSuccess', function (event, current, previous) {
// current is the current route
// previous is the previous route
});
...
});
Angular Doc