I have a problem with migrating from ngroute to ui.router:
using ngroute i have couple angular files:
module.js
angular.module('betTogether', ['ngRoute']);
route.js
angular.module('betTogether').config(['$routeProvider',
function (
$routeProvider
) {
$routeProvider.
when('/descriptionBets', {
templateUrl: 'descriptionBets',
controller: 'descriptionBetsCtrl'
}).
when('/normalBets', {
templateUrl: 'normal',
controller: 'normalBetsCtrl'
}).
when('/addBet', {
templateUrl: 'addBet',
controller: 'addBetCtrl'
}).
otherwise({
redirectTo: '/descriptionBets'
});
}]);
normalBets.js
angular.module('betTogether').controller('normalBetsCtrl', [
'$scope','$http',
function($scope,$http){
$scope.typeBetsImages = [{link: "images/basketball.png", title:"basketball"},
{link: "images/tenis.png", title: "tenis"},
{link: "images/volleyball.png", title: "volleyball"},
{link: "images/football.png", title:"football"}
];
$http.get("/normalBets").success(function(data){
$scope.normalBets = data;
});
}]);
...and rest of controllers. And everything works ok.
Now i want to migrate to ui-router. so i change module.js and route.js like that:
module.js
angular.module('betTogether', ['ui.router']);
route.js
angular.module('betTogether').config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider){
// For any unmatched url, send to /business
$urlRouterProvider.otherwise("/descriptionBets")
$stateProvider
.state('descriptionBets', {//State demonstrating Nested views
url: "/descriptionBets",
templateUrl: "descriptionBets",
controller: "descriptionBetsCtrl"
})
.state('normalBets', {//nested state [products is the nested state of business state]
url: "/normalBets",
templateUrl: "normal",
controller: "normalBetsCtrl"
})
.state('addBet', {//nested state [services is the nested state of business state]
url: "/addBet",
templateUrl: "addBet",
controller: "addBetCtrl"
});
}]);
and it doesnt work. i have error:
Error: [$injector:nomod] http://errors.angularjs.org/1.3.10/$injector/nomod?p0=betTogether angular.min.js:6:417
... and it is for 1st line of each controllers.
Someone could help me?
PS: sorry for my english, hope You understand all.
Check the order of your <script> imports in your index.html. The likelihood is that you've included the ui-router module after your betTogether module whereas it should come before it because betTogether depends on ui.router.
Related
I am trying to capture a route to be something like
www.mysite.com/#name=ted&location=ca
I am using stateprovider and I setup as follow:
$stateProvider
.state('home', {
url: '/#name',
controller: function () {
alert('here')
do stuff...
}
})
but for some reason, alert never trigger.
Can someone help me about it? Thanks a lot!
To get params via query string you can use try:
$stateProvider
.state('home', {
url: '/?name&location',
controller: function () {
alert('here')
do stuff...
}
})
# will be there if HTML5 mode is disabled.
var app= angular.module('appName', []);
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/home', {
templateUrl: 'templates/home.html',
controller: 'AddOrderController'
}).
when('/contact', {
templateUrl: 'templates/contact.html',
controller: 'ShowOrdersController'
}).
otherwise({
redirectTo: '/home'
});
}]);
Try This Is Example Of Navigation Using With route Providers .
When using ui.router, all routes need a template, include that in your state, remove the # sign from the URL and it should work
I am having an issue where once the templateUrl is added into the ui-router child state, the application will no longer perform the routing to the state. It works fine when it's just a template.
app.js:
app.config(['$stateProvider', '$locationProvider', '$urlMatcherFactoryProvider', '$urlRouterProvider',
function ($stateProvider, $locationProvider, $urlMatcherFactoryProvider, $urlRouterProvider) {
$urlMatcherFactoryProvider.caseInsensitive(true);
$urlMatcherFactoryProvider.strictMode(false);
$urlRouterProvider.otherwise('/page-not-found');
$stateProvider
.state('dashboard', {
url: '/',
views: {
'header': {
template: 'header'
},
'nav': {
template: 'nav'
},
main: {
template: 'You are on the homepage'
}
}
});
$locationProvider.html5Mode(true);
}]);
app.run(['$rootScope', 'userService', '$state', function ($rootScope, user, $state) {
$rootScope.$on("$stateChangeError", console.log.bind(console));
if (!user.exists) {
$state.go('user.reg');
}
}]);
User.states.js:
.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('user', {
url: '/users',
abstract: true,
views: {
'header': {},
'nav': {},
'main': {
template: '<ui-view/>'
}
}
})
.state('user.reg', {
url: '/register',
//template: 'This will show fine',
templateUrl: '/app/Users/User.login.html' // this will break
});
}]);
UPDATE
If I add a ui-sref="user.reg" to my initial pages I can navigate to the state/page fine, with the templateUrl and template . So its just an issue when I try to use state.go('user.reg');
This means a work around is using the $location provider to change the path. Has the same effect but does seem rather wrong
The problem is with your relative paths.
Look at this code:
$locationProvider.html5Mode(true);
You have html5 mode enabled, and for that to work, you have your base ref set in your html, which probably looks like this:
<base href="/">
Your issue is likely that the route for your template isn't "yoursite.com/app/Users/User.login.html."
See this Plunker for a working version of your code. Then go into the html code and uncomment out the base tag, and notice that it will break.
I am setting up a scaffold for an app with angular and angular-ui-router. I have it working however it seems to be adding a hash into my url (I'm running dev on localhost) localhost:9000/#/test. When I land on the main page it's just localhost:9000 and it still serves the main view content. I would like to get rid of the hash if possible.
So here is my setup:
In my index.html in the body I just have my nav and then the ui-view under that:
<div class="row">
<ul class="nav navbar-nav">
<li><a ui-sref="index">Home</a></li>
<li><a ui-sref="test">Test</a></li>
</ul>
</div>
<div ui-view=""></div>
and in my app.js I just have:
angular
.module('playApp', [
'ui.router'
])
.config(function($stateProvider) {
$stateProvider
.state('index', {
url: '',
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.state('test', {
url: '/test',
templateUrl: 'views/test.html',
controller: 'testCtrl'
});
});
So when I land, it's fine, but when I start using the nav I have set up, it adds the hashes to the url, would prefer not to have them if possible. Thanks!
Include $locationProvider and do $locationProvider.html5Mode(true); :
angular.module('playApp', ['ui.router'])
.config(function($stateProvider, $locationProvider) {
$stateProvider.state('index', {
url: '',
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.state('test', {
url: '/test',
templateUrl: 'views/test.html',
controller: 'testCtrl'
});
$locationProvider.html5Mode(true);
});
I also have an otherwise in there as well, so that if it can't find a specified route, it will just default back:
angular.module('playApp', ['ui.router'])
.config(function($stateProvider, $locationProvider, $urlRouterProvider) {
$stateProvider.state('index', {
url: '',
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.state('test', {
url: '/test',
templateUrl: 'views/test.html',
controller: 'testCtrl'
});
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/');
});
Inject $locationProvider into your config and set html5mode to true:
angular.module('playApp', [
'ui.router'
])
.config(function($stateProvider, $locationProvider ) {
$stateProvider
.state('index', {
url: '',
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.state('test', {
url: '/test',
templateUrl: 'views/test.html',
controller: 'testCtrl'
});
$locationProvider.html5Mode(true);
});
Make sure you adjust your .htaccess to handle this (rewriting back to root).
There is an alternative to html5Mode. But it has its drawbacks.
When defining ui-router states, the url option is not required. From that documentation:
You might create some child states without URLs, if it doesn’t make sense to bookmark those child states. The state machine transitions between url-less states as usual, but does not update the url when complete. You still get all the other benefits of a state transition such as parameters, resolve, and lifecycle hooks.
If you don't need to provide a URL for a state so that users can bookmark those states, you can omit the url option. The URL won't change.
I have the following code in my app.js:
var myApp = angular.module('myApp', ['ngRoute'])
myApp.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider.
when('/products', {
templateUrl: '/angularjs/public/angular/views/product.html'
}).
otherwise({
templateUrl: '/angularjs/public/angular/views/home.html'
});
$locationProvider.html5Mode(true);
}]);
When I go to home at http://localhost/angularjs/public, the .otherwise kicks in correctly.
If I go to http://localhost/angularjs/public/products, nothing happens, or more precisely, I believe .otherwise is invoked again, since is displayed the home.html view. Also no error is throwed in batarang's console.
What could be the problem?
you need to add "public" to product slug in your route
when('public/products', {
templateUrl: '/angularjs/public/angular/views/product.html'
}).
I am trying to do what was essentially answered here Unable to open bootstrap modal window as a route
Yet my solution just will not work. I get an error
Error: [$injector:unpr] Unknown provider: $modalProvider <- $modal
My app has the ui.bootstrap module injected - here is my application config
var app = angular.module('app', ['ui.router', 'ui.bootstrap','ui.bootstrap.tpls', 'app.filters', 'app.services', 'app.directives', 'app.controllers'])
// Gets executed during the provider registrations and configuration phase. Only providers and constants can be
// injected here. This is to prevent accidental instantiation of services before they have been fully configured.
.config(['$stateProvider', '$locationProvider', function ($stateProvider, $locationProvider) {
// UI States, URL Routing & Mapping. For more info see: https://github.com/angular-ui/ui-router
// ------------------------------------------------------------------------------------------------------------
$stateProvider
.state('home', {
url: '/',
templateUrl: '/views/index',
controller: 'HomeCtrl'
})
.state('transactions', {
url: '/transactions',
templateUrl: '/views/transactions',
controller: 'TransactionsCtrl'
})
.state('login', {
url: "/login",
templateUrl: '/views/login',
controller: 'LoginCtrl'
})
.state('otherwise', {
url: '*path',
templateUrl: '/views/404',
controller: 'Error404Ctrl'
});
$locationProvider.html5Mode(true);
}])
I have reduced my controller to the following:
appControllers.controller('LoginCtrl', ['$scope', '$modal', function($scope, $modal) {
$modal.open({templateUrl:'modal.html'});
}]);
Ultimately, what I am hoping to achieve is when login is required not actually GO to the login page, but bring up a dialog.
I have also tried using the onEnter function in the ui-router state method. Couldn't get this working either.
Any ideas?
UPDATE
Ok - so as it turns out, having both ui-bootstrap.js AND ui-bootstrap-tpls breaks this - After reading the docs I thought you needed the templates to work WITH the ui-bootstrap. though it seems all the plunkers only load in the ..tpls file - once I removed the ui-bootstrap file my modal works...Am i blind? or doesn't it not really say which one you need in the docs on github? -
Now i just need to figure out how to prevent my url from actually going to /login, rather than just show the modal :)
update 2
Ok, so by calling $state.go('login') in a service does this for me.
Hi I had a hard time getting through the similar problem.
However, I was able to resolve it.
This is what you would probably need.
app.config(function($stateProvider) {
$stateProvider.state("managerState", {
url: "/ManagerRecord",
controller: "myController",
templateUrl: 'index.html'
})
.state("employeeState", {
url: "empRecords",
parent: "managerState",
params: {
empId: 0
},
onEnter: [
"$modal",
function($modal) {
$modal.open({
controller: "EmpDetailsController",
controllerAs: "empDetails",
templateUrl: 'empDetails.html',
size: 'sm'
}).result.finally(function() {
$stateProvider.go('^');
});
}
]
});
});
Click here for plunker. Hope it helps.
I'm working on something similar and this is my solution.
HTML code
<a ui-sref="home.modal({path: 'login'})" class="btn btn-default" ng-click="openModal()">Login</a>
State configuration
$stateProvider
// assuming we want to open the modal on home page
.state('home', {
url: '/',
templateUrl: '/views/index',
controller: 'HomeCtrl'
})
// create a nested state
.state('home.modal', {
url: ':path/'
});
Home controller
//... other code
$scope.openModal = function(){
$modal.open({
templateUrl: 'path/to/page.html',
resolve: {
newPath: function(){
return 'home'
},
oldPath: function(){
return 'home.modal'
}
},
controller: 'ModalInstanceController'
});
};
//... other code
Finally, the modal instance controller.
This controller synchronizes the modal events (open/close) with URL path changes.
angular.module("app").controller('ModalInstanceController', function($scope, $modalInstance, $state, newPath, oldPath) {
$modalInstance.opened.then(function(){
$state.go(newPath);
});
$modalInstance.result.then(null,function(){
$state.go(oldPath);
});
$scope.$on('$stateChangeSuccess', function () {
if($state.current.name != newPath){
$modalInstance.dismiss('cancel')
}
});
});
You may create a state with the same templateUrl and controller as your page where you want to show the modal, adding params object to it
$stateProvider
.state('root.start-page', {
url: '/',
templateUrl: 'App/src/pages/start-page/start-page.html',
controller: 'StartPageCtrl'
})
.state('root.login', {
url: '/login',
templateUrl: 'App/src/pages/start-page/start-page.html',
controller: 'StartPageCtrl',
params: {
openLoginModal: true
}
})
And in controller of the page, use this parameter to open the modal
.controller("StartPageCtrl", function($scope, $stateParams) {
if ($stateParams.openLoginModal) {
$scope.openLoginModal();
}
I found a handy hint to get this working. There are probably caveats, but it works for me. You can pass a result still but I have no need for one.
Using finally instead of the then promise resolve sorted this for me. I also had to store the previous state on rootScope so we knew what to go back to.
Save previous state to $rootScope
$rootScope.previousState = 'home';
$rootScope.$on('$stateChangeSuccess', function(ev, to, toParams, from, fromParams){
$rootScope.previousState = from.name;
})
State using onEnter
$stateProvider.state('contact', {
url: '/contact',
onEnter: function ($state, $modal, $rootScope){
$modal.open({
templateUrl: 'views/contact.html',
controller: 'ContactCtrl'
}).result.finally(function(){
$state.go($rootScope.previousState);
})
}
});