How to Pass Variables When Using $routeProvider - angularjs

I'm using $routeProvider to create a one page app where users press continue to go to the next step. It is important to pass variables to the next page whenever a user clicks continue so I followed some advice and created my own service which has persistent variables. This all works great except that I can only get variables from the service, I don't know how to update the variables. Here is my code:
myApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/pick_categories', {
templateUrl: '/pick_categories.html',
controller: 'MeetupDataCtrl'
}).
when('/pick_times', {
templateUrl: '/pick_times.html',
controller: 'MeetupDataCtrl'
}).
when('/events', {
templateUrl: '/events.html',
controller: 'MeetupDataCtrl'
}).
otherwise({
redirectTo: '/pick_categories'
});
}]);
myApp.service("meetupService", function(){
this.checked_categories = [];
});
myApp.controller('MeetupDataCtrl', ['$scope', '$http', '$location', '$resource', 'meetupService', function MeetupDataCtrl($scope, $http, $location, $resource, meetupService) {
$scope.checked_categories = meetupService.checked_categories;
}]);
Then in the view I have checked_categories bound to an input field.
I know the problem is that I'm getting the service's variables on init, but I'm not updating the service's variables from the scope after I change routes. Any ideas on how I could do this? (or if there are other best practices)

You could in fact change the service properties directly ... :
meetupService.checked_categories.push({ something: 'something'});
... but it's better to encapsulate the state properties of a service so you can do something like the following from your controller:
meetupService.addCategory('theCheckedCategory');
Do mind that services are singletons in Angular; there will be only one meetupService in your Angular application. This means that once the user has modified the checked_categories array somehow they will have that some array until they refresh/reload your website.
Also note that passing state information via url arguments is in most cases not necessary when building a single page app (which Angular is).
It sounds like your trying to build a wizard and if I'm guessing right you don't need anything of the above. Wizards are actually quite easy to make in Angular because all the state information is kept, ... well as long as you want it to.
See this plunker for a simple wizard example.
Edit:
Oh, and if you really need to pass arguments to the route, you can do that with the builtin $location service.
// change the path
$location.path('/newValue')
// change the query string / url arguments
$location.search({myArg: 'value', myOtherArg: 'anotherValue'});

Related

Angular js use $windows from directive code

OK, just when I think I understand AngularJS I get zapped.
I have an application that uses a number of different google maps. I want the user to click on a marker and then have the system so to a new screen with information relating to what was clicked.
Everything is working well up to a point. I get the click event and then get ready to go to the appropriate screen. My code at that point looks like:
$window.location.href = "#/" + ScreenName + "/" + Parameter ;
At this point I get the error:
ReferenceError: Can't find variable: $window
Which searching tells me I need to inject $window
I have tried a bunch of different ways to do this injection, but this is also where my personnal knowledge base fails me.
I think I need to have my app.js file look like this:
.config([
'$routeProvider',
function($routeProvider)
{
$routeProvider.
when("/customer/:cust_gid", {templateUrl: "views/div_Cust.html", controller: "customerController"}).
when("/location/:locn_gid", {templateUrl: "views/div_Locn.html",controller: "locationController"}).
otherwise({redirectTo: '/utilities'});
}])
.config(function ($windowProvider) {
var $window = $windowProvider.$get();
console.log($window);
});
This does nothing for me. I need to know If I am close and just don't have the syntax right or is there something else missing.
Do I need an include file in my index.html file to load $windows?
Can someone give me a kindergarten level answer to this question.
Appreciate
Stan
$windows is a globally service which is included in angularjs.
You don't need an extra library reference for it.
To use it, just inject is as any other service in the controller which should use it
app.controller('locationController', function($scope, $window)..

From 1 to 3 controllers in Angular

I'm new to angularJS so I'm still learning the "angular way" of doing things and therefore seek for advice.
I started building my login/register/forgotten_password views which now work perfectly fine. So the routing looks basically like this:
mainApp.config(function ($routeProvider) {
$routeProvider
.when('/login',
{
controller: 'loginCtrl',
templateUrl: 'views/login.html'
})
.when('/register',
{
controller: 'registerCtrl',
templateUrl: 'views/register.html'
})
.when('/dashboard',
{
controller: 'dashboardCtrl',
templateUrl: 'views/dashboard.html'
})
})
Now here's the problem and/or question I have :
After a successful login, you get redirected to the dashboard which gets loaded into ng-view. The dashboard is indeed the view but there should be more controllers and templates once you enter the app (sidebar, topbar, chat...).
How would you approach this ?
I also have a globalCtrl on the html element to handle other things, just in case that information might be helpful in any way.
You shouldn't think in controllers anymore. Rather think in "components". There are lots of articles on the internet on how to learn this (better) approach. Here is one to start: Refactoring Angular Apps to Component Style
tl;dr; Create a component (element directive) for every section/part of your view. In your case a <dashboard>, <sidebar>, <topbar>, ...
You can (and should) route to components! See this issue for more information. Here is a "real life" example on how to achieve this: https://github.com/ui-router/sample-app-ng1
This is the con giving of using $routeProvider in Angular JS. When you use a $routeProvider to define routes in angular JS, a single route can only point to a single view and there is no concept of nested views using $routeProvider.
And when you talk about having more than one template inside the view, you are talking about having nested views inside a single view. Unfortunately Angular's $routeProvider doesn't provide that. But now comes the ui-router, which replace the concept of route with states. You can define multiple sub states in a state and each sub state can point to different template. Look at the following link and follow simple steps to power up views and nested views in your app.
ui-router

Populate Scope Values from URL on Initial Load

I am new to Angular so bear with me.
I have a controller that handles the search functionality within a page.
As a user changes the search the url changes to reflect the user interaction. Then there are $http.post calls to an API to retrieve those values within the URL. A repeater in a separate controller is updated appropriately.
This works great and the scope changes correctly.
But how do I handle initial load?
If a user clicks a saved search.
Example:
http://blah/blah/blah/Search/Status-1%7CBeds-3
I would want the search fields and the scope to be set appropriately but then the same functionality should continue.
What is the best way of doing this?
If code is needed then ask, but this is more of a which direction to go question then a fix my code question.
You probably want AngularJS routing and the $routeParams object.
If that is not adequate, you can use the $location service to extract information from the URL and write it to the $scope in your controller constructor function.
If you use ui-router you can define the search string as a parameter that can be used when deep linking
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url:'/home',
templateUrl: 'templates/home.html',
controller: 'HomeController'
})
.state('search', {
url: '/search/:searchtoken',
templateUrl: 'templates/search.html',
controller: 'SearchController'
});
http://www.funnyant.com/angularjs-ui-router/
One solution is to populate the search variable with the url params. Something like:
if params
$scope.searchInputVal = params
$scope.doPostRequest()
(sorry for the coffee script syntax)
and just ensure whatever function you have to update these search parameters is firing onChange() or onClick() whichever you're using to fire the post request to begin with.

Unable to route non existing paths in Angularjs

I am unable to route the path code/:code in my website. I receive the following error:
Firefox can't find the file at /C:/Code/dola/mobileweb/app/code/123
default.htm is located in the app folder.
I am using the mobileangularui framework. I have the following routes declared (among others):
app.config(function ($routeProvider) {
$routeProvider.when('/', { templateUrl: 'codeview.htm', reloadOnSearch: false });
$routeProvider.when('/code/:code', { templateUrl: 'codeview.htm', reloadOnSearch: false });
});
Everything works fine, except when I try e.g. code/12345.
This route is intended for a call from outside, e.g. www.mywebsite.com/code/12345.
I see two issues. First is re-declaring the $routeProvider unnecessarily. The second is you don't have an "otherwise" clause to catch everything you aren't already.
Also, not an error, but good practice to follow; you are missing a controller and controllerAs explicit directive for each entry. Try this:
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'codeview.htm'
, controller: 'HomeController'
, controllerAs: 'vm'
, reloadOnSearch: false
})
.otherwise({
redirectTo: '/'
})
});
This was based on the assumption that '/code/:code' is not its own page. The option is easy to add/change if this is not the case, following the above model.
Hope this helps.
-C§
-edit-
It looks as though the best way to do this (as with what I've done in my current project for such needs) is to store the code into a global (model) variable and call the redirect using $location.path('/');. Something like the below would be part of the click-function:
DataService.code = vm.code; //the code value selected
$location.path('/');
And the resulting page would have as part of its initialization routine:
vm.code = DataService.code; //retrieves the code from memory
//and uses it to populate the page appropriately
I'm unfamiliar with how to specify a URL and have it read what page it should populate based on the trailer, aside from using PHP to catch the URL extension with the index and a $_GET redirection process. I know this can be achieved using AJAX or a Jquery catch, but I'm still somewhat new to JavaScript as a whole and not sure what the process would look like.
Alternatively, you could designate a page for each possible code (ex: 12345.html || 12345.php).
Hope this also helps.
-C§

How to set in angularjs templateUrl to location.pathname in otherwise clause

I'm new to angularjs and want to integrate it in a cakephp app. For some pages I don't have a controller since no javascript is exectuted there or because I still have to create them. I however don't want to list them all in the routes. For this reason i set it like the following:
angular.module('desktop', []).
config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when('/', {templateUrl: 'pages/index', controller: IndexController})
.when('/clubs', {templateUrl: 'partials/clubs.html',controller: ClubListController})
.otherwise({templateUrl: location.pathname});
}]);
This is however not working. When I go to /help, nothing happens. What am i doing wrong?
From my comments:
As far as I know it there is currently no way to do this with just routes. Routes are made to be static, they are defined as the app loads and do not update dynamically as time goes by. So using location.pathname() (or directly checking window.location) won't work since the route be set to whatever the value is when the app starts, and then never change again. It won't update when you load a new path unless you do a full browser reload (this is btw possible, but a hacky sollution).
But people have been working around it using includes, which might work for you depending on what you are after. See this question and the accepted answer for an example of how this works.
AngularJS - How to use $routeParams in generating the templateUrl?

Resources