I am using ui-router for my router. I want to implement i18n and for it I've created the following states
$stateProvider
.state('main', { url: '/:lng', abstract: true, template: '<div ui-view></div>'})
.state('main.index', { url: '/', templateUrl: '/views/index.html'})
.state('main.gallery', { url: '/gallery', templateUrl: '/views/gallery.html', controller: 'GalleryCtrl'})
And created the following links
a(ui-sref='main.index') Home
a(ui-sref='main.gallery') Gallery
However this links look like:
for index //
for gallery //gallery
I have found out that in uiSref directive he cannot inherit params from abstact main state.
Am I doing wrong with states?
Upadate:
I have one problem. I binded params to the scope object. In the ui-sref directive there is a watcher that tracks the params change, but in the handler of the watcher there is the following checking
if (newVal !== params) update(newVal);
However, when I try to debug the params is changing to the new param (I actually don't understand how, because params is assigned only once) and in the if check newVal === params
params = $scope.$eval(attr.params) //something like this
I even tried to use Object.observe on param object but it doesnot trigger before "watch" handler is triggered.
Now, I changed if check to make my code work.
There's nothing wrong with your state definitions from what I gather, but you're not passing any parameters to your ui-sref? Your state main.index & main.gallery still expect you to give it.
Working plunkr: http://plnkr.co/edit/uaII8LkMKoAHnacrLybQ?p=preview (Launch it seperate window to see url changes)
HTML:
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#*" data-semver="1.2.14" src="http://code.angularjs.org/1.2.14/angular.js"></script>
<script data-require="ui-router#*" data-semver="0.2.8" src="http://angular-ui.github.io/ui-router/release/angular-ui-router.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h1>Hello Plunker!</h1>
</body>
<a ui-sref='main.index({lng:5})'>Home</a> <br/>
<a ui-sref='main.gallery({lng:5})'>Gallery</a>
</html>
JS:
// Code goes here
angular.module("app", ["ui.router"]).config(["$stateProvider",
function($stateProvider) {
$stateProvider
.state('main', {
url: '/:lng',
abstract: true,
template: '<div ui-view></div>'
})
.state('main.index', {
url: '/',
template: '<span>Index</span>'
})
.state('main.gallery', {
url: '/gallery',
template: '<span>Gallery</span>',
})
}
]);
Related
Im fairly new to angular UI. I am trying to have a ui-view that has a child a tag that has an sref that will change its parent ui-view
Something like this:
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div ng-app="app">
<h1>Hello</h1>
<ul>
<li>
<a ui-sref="organisations">Click 1</a>
</li>
</ul>
<div ui-view="testview"></div>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.1/angular-ui-router.min.js"></script>
<script>
angular
.module('app', ['ui.router'])
.config(setViewStates)
;
function setViewStates($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
// Organisations
.state('organisations', {
url: '/',
views: {
'testview': {
template: '<p>view 1</p><a ui-sref="organisations.club">Click</a>',
},
}
})
.state('organisations.club', {
url: '/club',
views: {
'testview#': {
template: '<p>view 2</p>',
controller: function($scope) {
console.log('hello');
}
},
}
});
;
}
</script>
</html>
This is a small mockup of what I'm intending to do but ultimately, all I want to do is have a template with a table of items, and once you press on one of those items, the table template would be replaced with the details of that item, along with its state and url.
So the hierarchy is something like:
/club/list
/club/:clubId
.state('organisations', {
url: '/:id',
views: {
'testview': {
template: '<p>view 1</p><a ui-sref="organisations({id : id_of_this_file})">Click</a>',
},
}
})
if you have only one state with params as id, you can send id as new or any other keyword for the first time and manipulate the html with ng-if on whether you receive id as 'new' or the file id. if you receive new in id parameter show the table else if you receive proper id show the file data.
I have created a plunker repro here: http://plnkr.co/edit/zU3PtJamS61Ac0bAKToD?p=preview
When you go to the projects tab and click the Edit button I would expect that the Edit.Html view is rendered in the ui-view "outer".
When I debug then even the ProjectsEditController is created but the state is not really activated and the ui sticks to the projects view.
What do I wrong?
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<link rel="stylesheet" href="style.css" />
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.3/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap-tpls.min.js"></script>
<script src="http://angular-ui.github.io/ui-router/release/angular-ui-router.js"></script>
<script src="app.js"></script>
<script src="AdministrationController.js"></script>
<script src="ProjectsController.js"></script>
<script src="ProjectsEditController.js"></script>
<script src="SettingsController.js"></script>
</head>
<body ng-app="routedTabs" >
<div class="wrapper">
<div ui-view="outer">
<header class="aside">thats the header </header>
<div ui-view="menu" id="menu" class="aside">this is the menu aside</div>
<div ui-view="content" class="main container">
<h1>Working on it... </h1>
</div>
</div>
</div>
</body>
</html>
Edit.html
<div ng-bind="title"></div>
<button ui-sref="main.projects.edit({id: 10})" class="btn btn-default primary">Edit</button>
app.js
var app = angular.module("routedTabs", ["ui.router", "ui.bootstrap"]);
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("");
$stateProvider
.state("main", {
abtract: true,
url: "",
views: {
'content#': {
templateUrl: 'administration.html',
controller: 'AdministrationController'
}
}
})
.state("main.projects", {
url: "/projects",
views: {
'menu#': {
template: 'test'
},
'planner#main': {
templateUrl: 'projects.html',
controller: 'ProjectsController'
}
}
}).state('main.projects.edit', {
url: '/edit/:id',
views: {
'outer#': {
templateUrl: 'edit.html',
controller: 'ProjectsEditController'
}
}
})
.state("main.tab2", {
url: "/settings",
views: {
'menu#': {
template: 'bla'
},
'planner#main': {
templateUrl: 'settings.html',
controller: 'SettingsController'
}
}
});
});
UPDATE
According to #Karthik`s statement I can not render the edit view into the "outer" ui-view.
I have prepared here a plunker without abstract main state and tabs. In this sample is just a projects view with an edit project button which should render the edit view into the ui-view called "outer" and indeeded it works!
http://plnkr.co/edit/ogQIpfHz7Cy9Jo03czKL?p=preview
So my new question is, what is the difference between those samples that it works in this plunker but not in the tabs plunker?
And how can I concretely make it work with tabs then?
Your projects is working and edit tab is displayed (if you debug your js code you will see it). In your case problem is in your AdministrationController.js.
On every update event form tabset is called go function with route /projects (current tab)
$scope.go = function(route){
$state.go(route);
};
This changes state back to main.projects so it seems like state was not changes which it actually was.
You probably want to re-write triggering within AdministrationController.js or found out why is update/go function triggered when leaving tab.
See if answer in this topic helps. You could use this approach instead of update function.
As temporary solution could be used something like:
$scope.go = function(route){
if($state.$current.name != 'main.projects.edit'){
$state.go(route);
}
}
I'm suffering a problem with ui-router when I add a wrong segment to the route.
An example... http://xxx.xxxxx.xxx/roles works fine. This is a route defined without parameters. But if I add another segment in the browse http://xxx.xxxxx.xxx/roles/kk the $urlRouteProvider.otherwise('/') does not work and the application is trying to load all web resources (css, html, javascript, etc.) from a route like http://xxx.xxxxx.xxx/roles/app/app.css returning a lot of errors in console.
This code is in my app.config:
$urlRouterProvider
.otherwise('/');
$locationProvider.html5Mode(true);
And this is an example of route definition:
angular.module('myApp')
.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('roles', {
url: '/roles',
templateUrl: 'app/modules/admin/roles/index.html',
controller: 'RolesCtrl',
authenticate: true
})
.state('logs', {
url: '/logs',
templateUrl: 'app/modules/admin/logs/index.html',
controller: 'LogsCtrl',
authenticate: true
})
.state('parameters', {
url: '/parameters',
templateUrl: 'app/modules/admin/parameters/parameters.html',
controller: 'ParametersCtrl',
authenticate: true
});
}]);
Any help with this behavior?
Regards
Jose
Not fully sure where is theissue here... but I created working plunker, which should help to see what is needed to see the HTML 5 and ui-router working together. In case that server side is configured properly, this should work out of the box. Please, check this firstly:
How to: Configure your server to work with html5Mode
Now, this would be adjusted state def, to show the deep url nesting:
$stateProvider
.state('roles', {
url: '/roles/:id',
...
})
.state('roles.logs', {
url: '/logs',
...
})
.state('roles.logs.parameters', {
url: '/parameters',
...
});
To make all these call below wroking:
<nav>
roles/11/<br />
roles/22/logs<br />
roles/33/logs/parameters<br />
</nav>
<nav>
<a ui-sref="roles({id:1})">roles </a><br />
<a ui-sref="roles.logs({id:2})">roles.logs</a><br />
<a ui-sref="roles.logs.parameters({id:3})">roles.logs.parameters</a><br />
</nav>
we have to not forget to properly set the base url, in our example:
<!DOCTYPE html>
<html ng-app="MyApp">
<head>
...
<base href="/cTRk4o9HRELCQ4OK/" />
But for plunker we should set that dynamically:
<script>
document.write('<base href="'+ document.location.pathname +'" />')
</script>
Check working example here
You also have to define an state that points to the otherwise url, this way UI Routers knows how to handle the default state.
var app = angular.module('demo', ['ui.router']);
app.config(function($stateProvider, $urlRouterProvider){
$stateProvider
.state('roles', {
url: '/roles',
templateUrl: 'roles.html'
})
.state('otherwise', {
url: '/',
templateUrl: 'otherwise.html'
})
$urlRouterProvider
.otherwise('/');
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://rawgit.com/angular-ui/ui-router/0.2.11/release/angular-ui-router.js"></script>
<div ng-app="demo">
<ul>
<li>Roles</li>
<li>Otherwise</li>
<li>Not Found</li>
</ul>
<ui-view></ui-view>
<script type="text/ng-template" id="roles.html">
<h2>Roles Template</h2>
</script>
<script type="text/ng-template" id="otherwise.html">
<h2>Otherwise Template</h2>
</script>
</div>
When I enter the route
\#\projects\100\dates\2014-01-01
in the url and press return I get the "projects" state.
I expected to trigger "projects.selected.dates" state.
Why does the routing not work? Actually it works locally on my machine without named view...
http://plnkr.co/edit/0DJ6W7QEPx2UzpdzDrVu?p=preview
'use strict';
angular
.module('projectplanner', ['ui.router'])
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/projects');
$stateProvider
.state('projects', {
url: '/projects',
views: {
'menu': {
template: 'Start your projects!'
},
'content': {
templateUrl: "projects.html",
controller: 'ProjectsController'
}
}
})
.state('projects.selected', {
url: '/:projectId'
})
.state('projects.selected.dates', {
url: '/dates/:date',
views: {
'menu': {
templateUrl: 'menu.html'
},
'content': {
templateUrl: 'dateplanner.html',
controller: 'DateplannerController'
}
}
})
});
<!DOCTYPE html>
<html ng-app="projectplanner">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.2.x" src="https://code.angularjs.org/1.2.20/angular.js" data-semver="1.2.20"></script>
<script data-require="ui-router#*" data-semver="0.2.10" src="https://rawgit.com/angular-ui/ui-router/0.2.10/release/angular-ui-router.js"></script>
<script src="app.js"></script>
<script src="ProjectsController.js"></script>
<script src="DateplannerController.js"></script>
</head>
<body>
<div class="wrapper" >
<header class="aside">Logo</header>
<div ui-view="menu" id="menu" class="aside"></div>
<div ui-view="content" class="main">
</div>
</div>
</body>
</html>
There is the updated and working plunker, and this is the essential update:
.state('projects.selected.dates', {
url: '/dates/:date',
views: {
'menu#': { // HERE is # added
templateUrl: 'menu.html'
},
'content#': { // HERE is # added
templateUrl: 'dateplanner.html',
controller: 'DateplannerController'
}
}
})
See the '#' at the end of the ui-view name
The full explanation is here:
View Names - Relative vs. Absolute Names (cite)
Behind the scenes, every view gets assigned an absolute name that follows a scheme of viewname#statename, where viewname is the name used in the view directive and state name is the state's absolute name, e.g. contact.item. You can also choose to write your view names in the absolute syntax.
So, what I did is use of the absolute name .. targeting the root - index.html
Some examples from documentation... greatly explaining that all:
$stateProvider
.state('contacts', {
// This will get automatically plugged into the unnamed ui-view
// of the parent state template. Since this is a top level state,
// its parent state template is index.html.
templateUrl: 'contacts.html'
})
.state('contacts.detail', {
views: {
////////////////////////////////////
// Relative Targeting //
// Targets parent state ui-view's //
////////////////////////////////////
// Relatively targets the 'detail' view in this state's parent state, 'contacts'.
// <div ui-view='detail'/> within contacts.html
"detail" : { },
// Relatively targets the unnamed view in this state's parent state, 'contacts'.
// <div ui-view/> within contacts.html
"" : { },
///////////////////////////////////////////////////////
// Absolute Targeting using '#' //
// Targets any view within this state or an ancestor //
///////////////////////////////////////////////////////
// Absolutely targets the 'info' view in this state, 'contacts.detail'.
// <div ui-view='info'/> within contacts.detail.html
"info#contacts.detail" : { }
// Absolutely targets the 'detail' view in the 'contacts' state.
// <div ui-view='detail'/> within contacts.html
"detail#contacts" : { }
// Absolutely targets the unnamed view in parent 'contacts' state.
// <div ui-view/> within contacts.html
"#contacts" : { }
im just starting to learn angular and ioninc to build an app.
I just started a new app with ionic included and made a list of items from a json file. This works perfect, but since im jump into routing i just see a blank page and i don't get my mistake.
this is my index.html:
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8">
<title>Spätifinder</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<link rel="stylesheet" href="css/ionic.css">
<script src="angular.min.js"></script>
<script src="js/ionic.bundle.js"></script>
<script src="app.js"></script>
</head>
<body ng-app="spaetifinder">
<ion-header-bar type="bar-positive"
animation="nav-title-slide-ios7"
back-button-type="button-icon"
back-button-icon="ion-ios7-arrow-back"></ion-header-bar>
<ion-nav-bar class="bar-energized nav-title-slide-ios7">
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
</body>
</html>
this is ma app.js file:
var app = angular.module('spaetifinder', ['ionic']);
app.config(function ($stateProvider, $urlRouterProvider) {
// 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
$stateProvider
.state('home', {
url: '/',
templateUrl: 'home.html'
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/home');
});
app.controller('StoreController', [ '$http', function($http) {
var store = this;
store.storeList = [ ];
$http.get('http://m.xn--sptifinder-r5a.de/apiv1/jsonp.php?action=list&lat=52.437595&long=12.987900&distance=100').success(function(data){
store.storeList = data;
});
this.loadImage = function(hasImage){
if(hasImage = 0) {
return "http://www.spätifinder.de/images/fotos/no-foto.jpg";
}
else {
return this.ID;
}
};
}]);
and this should be my template for home (home.html)
<!-- our list and list items -->
<ion-list>
<a href="#" class="item item-thumbnail-left" ng-repeat="spaeti in spaetis.storeList">
<img ng-if="spaeti.has_image == 0" ng-src="http://www.spätifinder.de/images/fotos/no-foto.jpg">
<img ng-if="spaeti.has_image == 1" ng-src="http://www.spätifinder.de/images/fotos/{{spaeti.ID}}_crop.jpg">
<h2>{{spaeti.Name}}</h2>
<p>{{spaeti.BusinessHours}}<br>{{spaeti.Street}}, {{spaeti.ZIP}} {{spaeti.City}}</p>
</a>
</ion-list>
Im just don't get it what is wrong with that, maybe you see an mistake there?
thanks in advance
luc
I think that your issue is in your routing configuration. You only define one state at the / URL. You then set your fallback to /home which doesn't exist. You probably want your home state to be located at /home.
EDIT: Scratch that i think i see your problem, you have a ; at the end of your state block, i had to remove mine to get it to work it took me along time last night to figure that our, hope it helps you.
Old answer:
Im not sure maybe this will help but here is mine, the only thing i see wrong with yours is what #Jon7 already pointed out.
.state('main', {
url: "/main",
templateUrl: "templates/main.html",
controller: 'MainController'
})
$urlRouterProvider.otherwise('/main');
I had some trouble understanding the routing too. I learned a lot from this Codepen example.
Codepen example routing
You need to add controller and perhaps a view as well...
so from this
.state('home', {
url: '/',
templateUrl: 'home.html'
});
to
.state('home', {
url: '/',
views: { //optional
'viewname':{
templateUrl: 'templates/home.html'
controller: 'StoreController'
}
}
});
Your mistake is the otherwise statement. It should be:
$urlRouterProvider.otherwise('/')
var app = angular.module('ionicApp', ['ionic'])
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/')
$stateProvider.state('home', {
url: '/',
template: '<p>Hello, world!</p>'
})
})
$stateProvider.state('home', {
url: '/',
templateUrl: 'home.html'
})
http://learn.ionicframework.com/formulas/navigation-and-routing-part-1/