I'm using Angular UI Router and I'm having trouble defining my routes.
I have some basic routes with states and URLs registered:
/about,
/register,
/ (Startpage).
When the user registers I want to give them a dynamic URL to their own personal page.
And this would be a paramaterized state.
I would like the URL to be http://www.whatever.com/[username]
and if the user does not exist, redirect to a 404.
However, If i register a state named '/{userName}' this conflicts with my other routes
and takes over all requests. How do I let through all statically registered routes?
I could do http://www.whatever.com/profile/[username]. But that's not what I, nor the client I'm developing for, wants.
Maybe I could use regexp to let the statically registered routes plus the base route '/'?
Maybe there is another great solution out there!
You can fix this by defining the wildcard route after the static routes.
Here's a plunker: http://plnkr.co/edit/4pBWkhq4FDhLWqdCfkES?p=preview
var app = angular.module('plunker', ['ui.bootstrap', 'ui.bootstrap.tpls', 'ui.router'])
.run(['$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}]);
app.config(function($stateProvider,$locationProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/about");
$stateProvider
.state('about', {
url: "/about",
views: {
"viewA": {
template: 'About'
}
}
})
.state('register', {
url: "/register",
views: {
"viewA": {
template: "Register"
}
}
})
.state('dynamic', {
url: '/{val}',
views: {
"viewA": {
template: "Dynamic route"
}
}
});
});
I've solved the problem.
It was all about the order of execution.
All my routes is being registered in the seperate config-block in their respective module.
and the config block with the '/' i.e. starroute had the wrong module-name. it was being registered into the 'app'-module when it was supposed to be registered into the 'app-startPage'-module. In that way it was always registered last, when it's supposed to be registered first!
Thanks anyway and hurray for copy-paste-mistakes!
Related
I'm using angular $stateProvider to allow routes throughout my app. I have an index.html and I am changing the html content inside using the following...
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/app');
$stateProvider
.state('app', {
url: '/app',
templateUrl: 'templates/menu.html',
controller: 'AppCtrl'
})
.state('app.accounts', {
url: '/accounts',
templateUrl: 'templates/accounts.html'
})
});
The first route works, when you open the app template/menu.html is put inside index.html. The problem occur when I try to change the state.
At the moment, I am implementing an API in my app, what the API does is irrelevant, but on success I want the API to change the state to app.accounts, see below...
app.controller('AppCtrl', function($scope, $ionicModal, $timeout) {
$scope.create = function() {
var linkHandler = Plaid.create({
env: 'tartan',
clientName: 'Example Project',
key: 'test_key',
product: 'connect',
//On success I want to change the state
onSuccess: function(token) {
window.location = '/app/accounts';
},
});
linkHandler.open();
}
});
Above, on success, I attempt changing the state, but when window.location is called, I get the error...
net::ERR_FILE_NOT_FOUND (file:///app/accounts)
I am not sure why I get this error because the first route works fine. Any idea how I can fix this?
Your path is wrong. That's what the error is saying. It can't find that route.
Try $window.location.href = "/#/app/accounts";
Remember to inject $window in the controller.
However a better way would be to inject the $state service and use it to navigate:
$state.go('app.accounts')
I'm using angular ui router to create a home route like this
routes.$inject = ['$stateProvider'];
export default function routes($stateProvider) {
$stateProvider
.state('home', {
url: '/',
template: require('./home.html'),
controller: 'HomeController',
controllerAs: 'home'
})
In the HomeController, I'm importing a service that provides a stream of blog posts. Thus, in the ./home.html template, I am iterating through the array of posts like this, creating links for each post
<span ng-repeat="post in home.posts">
<a ui-sref="home.detail({postId:post.id})">{{post.title.rendered}}</a>
</span>
As you can see from the link, I'm expecting a click of the link to be handled by home.detail state. In the router, I do this, expecting each post to have a url (when I click the links) something like http://localhost:8888/1 or http://localhost:8888/4. However, when I click the links, the url changes but the ./post.html template doesn't load and the log statement in the controller code below doesn't run. There are no errors in the console.
Question: why is the router code to handle the click of the individual links (to load the new template, to log the stateParams) not running when I click the links to the posts (yet the url changes)?
$stateProvider
.state('home', {
url: '/',
template: require('./home.html'),
controller: 'HomeController',
controllerAs: 'home'
})
.state('home.detail', {
url: '{postId:[0-9]{1,4}}',
template: require('./post.html'),
controller: ['$scope', '$stateParams',
function ( $scope, $stateParams) {
console.log($scope, "$scope", $stateParams, "$stateParams");
$scope.post = $stateParams;
}],
Your parent state needs a ui-view. From ui-router's documentation
Child states will load their templates into their parent's ui-view.
I am learning angularJS and creating a web application which uses ui-router.
I have defined states as follows:
angular.module('test', [])
.config(function($stateProvider){
$stateProvider.
state('root',{
url: '/',
abstract:true,
templateUrl: '/root.html',
controller: 'MyController'
})
.state('root.route1',{
url: '/route1',
parent: 'root',
views:{
'':{
templateUrl: '/route1.html'
}
'estimatedCost#':{
templateUrl: '/esitmatedCost.html'
}
}
})
.state('root.route2',{
url: '/route2',
parent: 'root',
views:{
'':{
templateUrl: '/route2.html'
}
'estimatedCost#':{
templateUrl: '/esitmatedCost.html'
}
}
})
});
While navigating back and forth between route1 and route2, I want to share scope variables from MyController. When I navigate to route2 from route1, it is loosing value of scope variable.
I am not sure what I am doing wrong.
Can anyone help me?
Thanks in advance.
I have yet to work with the ui-router, but I have worked with AngularJS for the last couple of years and this is how the language generally has worked in the past.
A controller's main purpose is to control the data on a single template. These controllers can communicate to each other through an AngularJS factory, often known as a service. In your case, you probably want to use a service as the controllers are getting destroyed on successful route change.
angular.module('test', [])
.factory('myFactory', function() {
var info = "Hello World";
return {
info: info
};
})
.controller('CtrlOne', function($scope, myFactory) {
$scope.info = myFactory.info;
})
.controller('CtrlTwo', function($scope, myFactory) {
$scope.info = myFacotry.info;
});
You can then use the two controllers on the two different views and they share the variables from the service that connects them.
Use $stateParams to pass parameters between two states.
Fallow the below steps :
Define your state with params object.
.state('route.route1', {
url: 'your url name',
params: {
nameOfParamObj: null
},
controller: 'your controller',
templateUrl: 'your template url',
})
From the controller where you want to send scope data use as fallows
$state.go(toState, params, options);
In toState controller catch state params using $stateParams
$stateParams.yourParamObjectName
Make sure $stateParams, $state services as dependency in your regarding controller
Have a look into the official ui-router documentation Here.
I've started developing a simple application :
in the first view I'm retreiving all the games, and the other view i'm retreivig the game details according to the game id.
I didn't link the two pages yet.
this is what i'm facing as problem. i'm confused ! should I use ion-view ?? or I should use a normal page
for each view I have a controller which look almost like :
.controller('tomorrowmatches', function($scope, $http) {
$http.get("http://www.myappbackend/ofc/matches?date=2015-05-03")
.success(function (response) {
$scope.matches = response;
}
});
})
and how to pass data from conroller to another, in my example I wanna pass the game.id as shwon on the screenshot.
if you need more details just let me know. I just need someone to make things clear for me, and if there is an example it would be fantastic.
To pass data to another view you can use the $state and $stateParams services.
Example
Controller 1 (sends the data)
.controller('MyCtrl1', function($scope, $state) {
$scope.selectedData = function(selectedId) {
$state.go('yourState', { id: selectedId });
};
})
Controller 2 (gets the data)
.controller('YourCtrl', function($scope, $state, $stateParams) {
if ($stateParams.id) {
$scope.yourParam = $stateParams.id;
}
// Do anything you want with the ID inside $scope.yourParam
})
app.js
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('init', {
url: "/init",
templateUrl: "templates/init.html",
controller: "MyCtrl1"
})
.state('yourState', {
url: "/yourState?id",
templateUrl: "templates/your-template.html",
controller: "YourCtrl"
})
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/init');
})
As you can see in the state yourState I assigned an id as a parameter. This parameter will be checked if exists by YourCtrl, if it exists assign to scope and then do whatever you want with it.
Remember to set the parameter options in your app.js route configuration.
Check the ui-router docs for more info on this. You have more ways to send data.
First of all you need the ion view as a container for your views/templates..
<body ng-app="myapp">
<ion-nav-view></ion-nav-view>
</body>
then on your app.js you need to configure your routing..
// Ionic Starter App
angular.module('myapp', ['ionic', 'myapp.controllers', 'myapp.services', 'myapp.directives'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider, $httpProvider) {
// Ionic uses AngularUI Router which uses the concept of states
// Learn more here: https://github.com/angular-ui/ui-router
// Set up the various states which the app can be in.
// Each state's controller can be found in controllers.js
// $httpProvider.defaults.useXDomain = true;
$stateProvider
//Page1
.state('page1', {
url: "/page1",
templateUrl: "templates/page1.html",
controller: "Page1Controller"
})
//Page2
.state('page2', {
url: "/page2",
templateUrl: "templates/page2.html",
controller: "Page2Controller",
})
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/page1');
});
Note: Make sure that all dependencies for ionic are included on your folder and called on your index.html..
Hope this helps :)
The site I'm building already has URL's built up using MVC. So for example /Account goes to a page, /Customers goes to a page, and /Quotes goes to a page. On the /Quotes page I have a multi-step wizard which I want to use Ui-Routing on. See my app.js below, this all works.
So my URL becomes /Quotes#newmodel, /Quotes#customer, etc. A different #{value} for each step on the wizard. The problem is that the .otherwise affects all other areas of the site. So if I'm going to /Account, I get the url /Account#wizard. I do not want this to occur anywhere other than on the /Quotes page. Is there anything I can do with the URL matching so I can remove the .otherwise?
'use strict';
var myApp = angular.module('myApp', ['ui.router']);
myApp.config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/wizard");
$stateProvider
.state('wizard', {
url: '/wizard',
templateUrl: 'Scripts/templates/wizardLayout.html',
controller: 'wizardNavigationCtrl'
})
.state('wizard.newmodel', {
url: '/newmodel',
templateUrl: 'Scripts/templates/wizardModel.html',
controller: 'wizardModelCtrl'
})
.state('wizard.other', {
url: '/other',
templateUrl: 'Scripts/templates/wizardOther.html',
controller: 'wizardOtherCtrl'
})
.state('wizard.customer', {
url: '/customer',
templateUrl: 'Scripts/templates/wizardCustomer.html',
controller: 'wizardCustomerCtrl'
})
.state('wizard.shipping', {
url: '/shipping',
templateUrl: 'Scripts/templates/wizardShipping.html',
controller: 'wizardShippingCtrl'
})
.state('wizard.review', {
url: '/review',
templateUrl: 'Scripts/templates/wizardReview.html',
controller: 'wizardReviewCtrl'
});
}]);
I'm also interested in how I can cause the route to load the layout and then by default go to the wizard.newmodel route (though this may be a separate question). Basically the same behavior as if I click on an:
<a sref-ui=".newmodel">
I removed the $urlRouterProvider.otherwise("/wizard") in the app.js.
Instead I added a controller to the main /Quote page that redirects the $location.url to '/wizard'. Below is the code.
myApp.controller('wizardCtrl', ['$location', function ($location) {
$location.url('wizard')
}])