Updating url on transition from child to parent state in UI router - angularjs

I have an Angular (1.2.1) app running UI-router (0.2.13), and the following state structure:
$stateProvider.state('home', {
template: "<div home></div>",
url: '/'
}).state('home.geo', {
url:'/geo/{geo}'
}
Transitioning from parent to child or between children with different {geo} parameter values works as expected. Transitioning from child to parent works - i.e. the contents of the template and $state.current change as expected - but the URL does not update in the browser.
To be clear, an example: I'm in /geo/california and I click a button with ui-sref='home'. I've confirmed that the correct href='#/' has been placed on the button, and clicking it causes the $state to transition back to the home state, but /geo/california remains in my address bar.
What am I missing here?
Update in respose to #UlukBiy's comment: No, home does not have a ui-view in its template. The ui-view is in the template of it's parent: The overall structure is:
<body>
<div app-nav></div>
<div ui-view></div>
</body>
So the home directive gets inserted into the ui-view, but it contains no ui-views of its own. Is that my problem? I'm new to UI-router, and assumed there was some low-level misunderstanding about the role of states vs. directives when I posted this. If so, please help me correct it.

This scenario should be working. There is a working example (click the blue button right-top to run example in separate window, showing the address bar)
I updated your state def a bit:
$stateProvider
.state('home', {
url: "/",
template: 'Home view <hr /> Geo view: <div ui-view></div>',
})
.state('home.geo', {
url:'^/geo/{geo}',
templateUrl: 'tpl.html',
})
All these links do work as expected:
<a href="#/home">
<a href="#/geo/california">
<a href="#/geo/czechia">
<a ui-sref="home">
<a ui-sref="home.geo({geo:'california'})">
<a ui-sref="home.geo({geo:'czech'})">
So, the most important change here is that for a child state we should use this url:
url:'^/geo/{geo}',
instead of the url:'/geo/{geo}'. Check the doc:
Absolute Routes (^)
If you want to have absolute url matching, then you need to prefix your url string with a special symbol '^'.
Check the working example here

Related

ui-router child view of an angularjs component not showing

I have an angularjs component(almost empty markup) acting as a shell/parent to its child views(markups with different columns/formats). I am able to see the component but no child views are loaded.
ui-router config code:
.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('parent', {
url: '',
views: {
'parentComponent': {
component: 'parentComponent'
}
}
})
.state('parent.child', {
url: '/child',
templateUrl: 'child.html'
});
index.html:
<body ng-app="app" >
<div ng-controller='RoutingCtrl'>
<parent-component></parent-component>
</div>
</body>
The parent, which is a component:
<!DOCTYPE html>
<div>
<br />
<br />
<div>I am the parent, a angularjs component.</div>
<div>There sould be the nested/child view right below:</div>
<div ui-view></div>
</div>
child:
<div>Hi! I am the child!</div>
My controller tells ui-router to go to child view:
$state.go('parent.child');
I don't want to declare parent as abstract because, in my real app, I have views parallel to the parent component view(together, they form a multiple named view) here and these other high level views(except the parent component) must be visible regardless of the child views.
I am using angularjs 1.5.8 and ui-router version 0.4.2
Plunker:
http://plnkr.co/edit/tBhVTjttMagaJzHQNvro?p=preview
You haven't provided any details what you are trying to accomplish, so based on what it looks right now, you have two options: either go with the ui-view template throughout your app and use the parent-child relationship of ui-router or go with hybrid approach of loading your component, and inside it, a state you want to show.
Example with parent-child relationship - This example uses ui-view throughout the app. parent-component is loaded with it's own state and it's not abstract. This approach is good if you want to load different templates for different states in the same place.
Example with hybrid approach. This example follows your current app structure with parent-component loaded in index.html and a state loaded in your parent-component. You can see that you really don't need a parent state here as you have put your parent-component directly in index.html file. State child is loaded in inside your parent-component and it doesn't need a parent state.

ui-sref set child view to parent view

I am using ui-sref for routing depending upon state.
Currently I am getting child's view inside parent as hierarchy. I want to assign a child's view to a parent view. Current state is as below plunker.
[link][//plnkr.co/edit/fpsTWglicbcGMotJIlll]
I want to see welcome after clicking click me.
If I understood your question correctly, the problem is you have inner as a child of tab1... so it is displayed in the ui-view of tab1. If you want it instead to make it replace tab1, then you don't need the ui-view in tab1.
Here's a forked plunker showing what I mean.
http://plnkr.co/edit/t4cxejVLGf4kywKp2bb5?p=preview
The parts I changed:
.state("main", { abtract: true, url:"/main", templateUrl:"main.html" })
.state("main.tab1", { url: "/tab1", templateUrl: "tab1.html" })
.state("main.inner",{
url:"/inner",
templateUrl:"inner.html"
})
.state("main.tab2", { url: "/tab2", templateUrl: "tab2.html" })
And in tab1.html
<div>
This is the view for tab1
<a ui-sref="main.inner">click me</a>
</div>
Is this what you're shooting for?
Add $scope.$state = $state;in the controller.
Then add ng-hide="$state.current.name === 'main.tab1.inner'" to
<h2 ng-hide="$state.current.name === 'main.tab1.inner'">View:</h2>
and
<div ng-hide="$state.current.name === 'main.tab1.inner'">
This is the view for tab1
<a ui-sref="main.tab1.inner">click me</a>
</div>
Here's the link [link] http://plnkr.co/edit/Yvlp6RNF69yiSq1HfMcf?p=preview

ui-route not redirecting to external page

From a modal dialog I present a general terms link that should redirect the user to a new page.
I would like to re-use my layout skeleton (background, logo ans basic styles) for the terms page, without the content of the master page (eg. search function, navigation etc). To achieve this I try to inject into a new window the terms template inside the ui-view="main" used for the normal site content (where is loaded the content of the modal dialog, as instance), but I get the error Could not resolve 'terms' from state 'login' (login is the current state where the modal dialog is).
Below the termsPage module with the ui-router state I would like to load:
angular.module('termsPage').config(function ($stateProvider) {
$stateProvider
.state('terms', {
url: '/terms',
views: {
'main': {
controller: 'TermsCtrl as Terms',
templateUrl: '/modules/staticPages/views/termsPage.html'
}
}
});
});
My index.html file:
<!-- Other tags excluded for sake of semplicity -->
<body ng-app="myApp">
<!-- Here I inject all the content -->
<div id="wrapper" ui-view="main">
</div>
Below the app module and view, where the content of the application is correctly loaded. Also the modal dialog from which I would like to redirect to the external page is loaded here.
angular.module('app').config(function($stateProvider){
$stateProvider
.state('app', {
url: '/app',
views:{
'main' : {
controller : 'AppCtrl',
templateUrl: 'modules/app/views/app.html'
}
}
});
});
Below app.html:
<div id="container">
<div class="browser">
<div class="content" ui-view="content" style="position:relative;">
</div>
My goal would be to create a sibling of app.html, injecting in main placeholder the content of my general terms page. Inside the modal dialog controller I use $state.go for the redirection:
$state.go('terms');
In my case the problem was that I did not registered the new module ('termsPage') as dependency in my main module:
angular.module('myApp', ['login','forms','termsPage'], function($urlRouterProvider){ ...}
Now that the module is registered, I can navigate correctly to state 'terms'.
Hopefully the case above might help someone else, getting hints for his/her case.

ui-router does not work with parameters in route

For some reason it does not work as expected for routes with parameters. It does not even render src attribute for such anchors. I made a simple plunk to demonstrate this and here is the code:
<body ng-controller="MainCtrl">
<a ui-sref="categories/foo">category</a>
<a ui-sref="blah">blah</a>
</body>
and routes:
$stateProvider
.state 'blah',
url: 'blah'
.state 'categories',
url: "categories/:name"
First work fine, second - not. Why this happening? What am I doing wrong?
to Navigate to state, with params
ui-sref also takes an state name as function like syntax with object of params(you want to pass to state) as an argument
So replace
<a ui-sref="categories/foo">category</a>
with
<a ui-sref="categories({name:'foo'})">category</a>
you can specify params like this (using the routes you have defined):
<a ui-sref="categories({name:'foo'})">category</a>

AngularJS + ui-router - lightbox overlay with deep links

I'm trying to use AngularJS to create a lightbox which contains url deeplinks. This works fine, but I need to name it for every page I want it to work on with the template behind it.
I can get this to work using ui-router and named views:
<ul>
<li><a ui-sref="home">Home</a></li>
<li><a ui-sref="portfolio">Portfolio</a></li>
<li><a ui-sref="videos">Videos</a></li>
</ul>
<div ui-view></div>
<div ui-view="overlay"></div>
And the javascript:
$stateProvider
.state('home', {
url: '/',
controller: 'HomeCtrl',
templateUrl: 'html/Home.html'
})
.state('portfolio', {
url: '/portfolio/:id',
controller: 'PortfolioCtrl',
templateUrl: 'html/Portfolio.html'
})
.state('videos', {
views: {
'overlay#': {
controller: 'VideosCtrl',
templateUrl: 'html/Videos.html'
}
}
});
Expected behaviour:
- click home, then click videos = shows videos overlay on home
- click portfolio, then click videos = shows videos overlay on portfolio page
Actual behaviour:
- click home, then click videos = shows videos overlay with blank page behind
- click portfolio, then click videos = shows videos overlay with blank page behind
Is there a way to have the named view update on any page leaving the existing ui-view intact?
You might look into using a modal for videos instead of the router if you want to overlay it on top of multiple states. If you stick with using the router, you might want to define videos as a child state of both home and portfolio instead of defining three states at the same level.

Resources