Angular breaks when I access page directly - angularjs

I have an Angular project that has some parts (specifically the top nav) broken when pages are accessed directly/reloaded. The rest of the page works fine. Only topnav having things like ui-sref not expanding to href and data not loading. I also noticed the topnav controller is not run at all when I reload/access the page directly.
In the ui-router config there is this app abstract route
$stateProvider
.state('app', {
url: '/app',
abstract: true,
templateUrl: helper.basepath('app.html'),
resolve: helper.resolveFor('fastclick', 'modernizr', 'icons', 'screenfull', 'animo', 'sparklines', 'slimscroll', 'classyloader', 'toaster', 'whirl', 'spinkit', 'akoenig.deckgrid')
})
It probably came with the theme the project is using. Anyways, in the app.html file
<!-- top navbar-->
<header ng-include="'app/views/partials/top-navbar.html'" class="topnavbar-wrapper"></header>
Then in top-navbar.html
{{'OUTSIDE'}}
<nav ng-controller="TopNavBarController" role="navigation" class="navbar topnavbar" style="background-color:#1663DE;">
{{'INSIDE'}}
The outside and inside are for debugging. I noticed on reload or when page is accessed directly, angular prints the OUTSIDE correctly in HTML but fails to print inside correctly. It appears on page as {{'INSIDE'}}. Which makes me think there is something wrong with the ng-controller. Removing ng-controller fixes this particular problem.
I added a log right after the controller function:
function TopNavBarController($scope, $state, SweetAlert) {
console.log('in TopNavBarController')
It appears the controller function is not even run? Whats wrong?
Only topbar is failing, the rest of the controller/application works fine. Data can be loaded, ui-sref expanding correctly.

Related

$urlRouterProvider.otherwise not going to default route

I am stuck with this for a while. I am very much new to ui-router's nesting of views. I am trying to route to default when "/" accessed. Here's my js file:
angular
.module("app")
.config(function($stateProvider,$locationProvider,$urlRouterProvider){
$urlRouterProvider.otherwise("dashboard");
$stateProvider
.state("home",{
url: "/",
templateUrl: "views/home/home.html"
})
.state("login",{
url: "/login",
templateUrl: "views/login/login.html"
})
.state("home.dashboard",{
url: "/dashboard",
templateUrl: "views/home/dashboard.html"
});
$locationProvider.html5Mode(true);
});
I don't know why that's not working. Every time I try to load localhost, it's not going to localhost/dashboard. Rather, it stops loading till home.html. Please help me in learning something new and showing my mistake.
Please see this working plunker. I turned off the HTML5 mode because it prevents plunker to work correctly.
The main problem with your code was that you were redirecting to /dashboard, in this statement:
$urlRouterProvider.otherwise("/dashboard");
Please note that home.dashboard is a child state of home. So, by default, the URL should be preceded by that of the home state. So the correct statement would be:
$urlRouterProvider.otherwise("/home/dashboard");
If you don't want the preceding /home, you need the change your route configuration for home.dashboard state to this:
.state("home.dashboard", {
url: "^/dashboard",
templateUrl: "dashboard.html"
});
The preceding ^ makes the URL absolute and makes it free of any preceding parent state's URL. So now, the statement $urlRouterProvider.otherwise("/dashboard"); will work as is.
After this change, the code could load the template home.html in the view. Further, you didn't have any ui-view directives in home.html in which the template of home.dashboard could load. So I added a <div ui-view></div> element in home.html to make it work correctly.

Angular templateUrl not redirecting to MVC controller

So I am having an issue in setting up my angular routes.
Moving straight to the point, my angular routes defined don't hit my mvc controller and thus action methods.
The action method return partial views, which represent my templates.
Here is an image of my route configuration.
Here is an image of my controller actions.
I am sure I am missing something, but can't seem to figure out what.
This example helps you to understand better about $routeProvider and $locationProvider.
The only issue I see are relative links and templates not being properly loaded because of this.
from the docs regarding HTML5 mode
Be sure to check all relative links, images, scripts etc. You must either specify the url base in the head of your main html file () or you must use absolute urls (starting with /) everywhere because relative urls will be resolved to absolute urls using the initial absolute url of the document, which is often different from the root of the application.
In your case you can add a forward slash / in href attributes ($location.path does this automatically) and also to templateUrl when configuring routes. This avoids routes like example.com/tags/another and makes sure templates load properly.
Here's an example that works:
<div>
Home |
another |
tags/1
</div>
<div ng-view></div>
And
app.config(function($locationProvider, $routeProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when('/', {
templateUrl: '/partials/template1.html',
controller: 'ctrl1'
})
.when('/tags/:tagId', {
templateUrl: '/partials/template2.html',
controller: 'ctrl2'
})
.when('/another', {
templateUrl: '/partials/template1.html',
controller: 'ctrl1'
})
.otherwise({ redirectTo: '/' });
});
If using Chrome you will need to run this from a server.
Well what worked for me was to remove the setting for the $locationProvider.html5Mode. As someone mentioned in another stack overflow post, here MVC5 and Angular.js routing - URLs not matching using the locationProvider in MVC seems to screw up the routing. I am still to investigate why exactly this happens, as all I thought it did was remove the '#' in the url, but seems like there's more to it

Angular ngRoute not working on reload with ngInclude

In case anyone else runs into the same issue. While trivial to some, it was not trivial for me.
The problem:
When the page loads ngRoute fails to load the shell (landing page) template when using ng-view inside ng-include.
However if we start navigating around the pages including navigating back to landing page then the template loads just fine. It is as if the first time the page loads it completely skips loading the landing template.
The setup:
Somewhere at the bottom of index.html's body:
<script src="angular-route.js"></script>
Somewhere in index.html template
<div ng-include="'root-shell.html'"></div>
Somewhere in root-shell.html template
<div ng-view></div>
The JS:
(function (/* IIFE enclosed code*/) {
angular('myApp', [$routeProvider]);
angular('myApp').config(function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'root-shell.html',
controller: 'RootShellController', // optional
controllerAs: 'rootShellCtrl' // optional
}).
.when('/about', {
templateUrl: 'about.html',
controller: 'AboutController', // optional
controllerAs: 'aboutCtrl' // optional
}).
otherwise({
redirectTo: '/'
});
});
})(/* IIFE invoke*/);
Why the problem?
Because if ng-view instantiation is delayed (through ng-include) then the $route instantiation is delayed as well. This means that $route will miss the location change event.
The fix:
Force a reload of the $route service.
angular('myApp').run(['$route', function($route) {
$route.reload();
}]);
Why does it work?
Because of angular's order of execution:
app config
app run
directive setup
directive compile
app controller
directive link
** Data resolve called **
new route's controller
and the run block:
Run blocks are the closest thing in Angular to the main method. A run block is the code which needs to run to kickstart the application. It is executed after all of the services have been configured and the injector has been created. Run blocks typically contain code which is hard to unit-test, and for this reason should be declared in isolated modules, so that they can be ignored in the unit-tests.
Disclaimer:
I am fairly new to Angular, therefore if I've misunderstood and/or misrepresented a concept then by all means chime in.

Angular Js + UI router, more than one module each with each owns ui routes config - how?

I have a main app on my application, called "bionico", this app utilizes UI-router
It has it's own $stateProvider configurations!
And that's fine, it works
BUT I needed to create a new module (cuz I'm trying to insert a step-by-step form on my application, you can find the code here: https://scotch.io/tutorials/angularjs-multi-step-form-using-ui-router)
To make this step-by-step form I need to create a new module with it's own $stateProvider configurations, the thing is that it doesn't work, I have included this module called "bionico.formApp" in my main app like this:
angular.module('bionico', ['ui.router', other modules, 'bionico.formApp'])
And that works fine, if I try to use a controller inside "bionico.formApp" it will also work fine. This is the code for this module:
// create our angular app and inject ngAnimate and ui-router
// =============================================================================
angular.module('bionico.formApp', ['ngAnimate', 'ui.router', ])
// configuring our routes
// =============================================================================
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('form', {
url: '/form',
templateUrl: 'templates/campaignForm/form.html',
controller: 'formCtrl'
})
// nested states
// each of these sections will have their own view
// url will be nested (/form/profile)
.state('form.profile', {
url: '/profile',
templateUrl: 'templates/campaignForm/form-profile.html'
})
// url will be /form/interests
.state('form.interests', {
url: '/interests',
templateUrl: 'templates/campaignForm/form-interests.html'
})
// url will be /form/payment
.state('form.payment', {
url: '/payment',
templateUrl: 'templates/campaignForm/form-payment.html'
})
// catch all route
// send users to the form page
$urlRouterProvider.otherwise('/form/profile');
})
// our controller for the form
// =============================================================================
.controller('formCtrl', function($scope) {
// we will store all of our form data in this object
$scope.formData = {};
$scope.test = "FUNCIONA";
// function to process the form
$scope.processForm = function() {
alert('awesome!');
};
});
But to make this form work I need to use <div ui-view></div> and when I put this on my file nothing happens, and I think it's because the app is using my main module "bionico" $stateProvider configurations and not "bionico.formApp"
Here is my html code:
<div ng-controller="formCtrl">
<!-- views will be injected here -->
<div ui-view></div>
{{test}}
the {{test}} from formCtrl works fine, it is printing the variable on my screen, but like I said ui-view is not. Is there a way to tell angular that I want to use "bionico.formApp" configurations and not the configs from my main module?
How would you solve this?
Like I think I have to tell angular that from that moment on I want to use "bionico.formApp" but I don't know how to do it.
I've tried
<div ng-app="bionico.formApp"> but nothing happened, not even errors
I saw then on stack over flow that I have to bootstrap it manually, but then I got an error saying that "bionico.formApp" had already been bootstraped
Update
People suggested that I only needed to rout stuff in only one module, but I needed two different default routs one for my main application and one or my form, but that wouldn't work.
and the reason why I was trying to make this work was because I needed a step by step form (wizard) on my application like this one: https://scotch.io/tutorials/angularjs-multi-step-form-using-ui-router)
But I've decided it is not worth the hassle, I'll try to find another wizard for angular js
I'm using now this walktrough wizard:
https://github.com/mgonto/angular-wizard
It was easy to install and it is very easy to customize the template, I recommend!

How to trigger router's state on page load?

In my app I have this server-generated link:
http://localhost:3000/people#/users
When I click on it I get redirected to the following HTML page with Angular UI-Router script:
<a ui-sref="users">Users</a>
<a ui-sref="invitations">Invitations</a>
<div ui-view></div>
The problem is - users state does not get triggered automatically on page load. I need to manually click on it and only then the corresponding UI-Router state gets triggered.
Here's my config file:
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('users', {
url: "/users",
templateUrl: "assets/partials/users.html"
})
})
There is a working plunker
$urlRouterProvider.otherwise('/users');
// States
$stateProvider
.state('users', {
url: "/users",
templateUrl: "assets/partials/users.html"
});
The $urlRouterProvider.otherwise('/users'); will redirect to defined page when none is provided
This links in index.html will work as well
href
<a href="#/users">
ui-sref
<a ui-sref="users">
Check it here
If that should be more dynamic, please check the:
Angular - Dynamically Choose Starting State
In case, that our issue is that application is working with this init page:
http://domain/app/
but not without the trailing slash
http://domain/app
We have to do some redirection on a server. (Redirection is needed to make all the relative path properly working) there are some how to with asp.net mvc
Browser address will not be displayed correctly in ui-route

Resources