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.
Related
I have an app that is currently using the angular ui-router module dependency. The only aspect of the ui-router that I'm currently employing is the ability to apply/modify $stateParams to $scope and vice versa so the URL can change the way data is displayed in the controller to a user on arrival (i.e. url?param=something will filter the data by something).
I have the following in my app.config to set the state:
$stateProvider
.state('root', {
url: '/?param',
templateUrl: 'template.html',
controller: 'listController',
params: {
param: {
value: 'something',
squash: true
}
}
});
On my homepage, template.html successfully loads when the app is instantiated as such:
<div ng-app="myApp">
<div ui-view>
</div>
</div>
However, I have reached a roadblock and realize that calling the template from within templateUrl isn't going to work, as this app is being built inside another framework and therefore needs to be called from within the homepage itself to access its full capabilities.
Being a noob at AngualrJS, I was wondering if anyone can tell me what the best way is to accomplish this while still keeping the logic of $stateParams and other ui-router capabilities intact for the future.
For instance, could I just remove the templateUrl parameter from my state and call the controller directly inside the ui-view like this:
<div ng-app="myApp">
<div ui-view>
<div ng-controller="listController">
do something
</div>
</div>
</div>
I also looked into changing the entire logic from using ui-router to simply using the $location service but I'm wondering if there is a way to accomplish this without needing to over-do everything.
$stateProvider
.state('dashboard', {
url:'/dashboard',
controller: 'MainCtrl',
templateUrl: 'views/dashboard/main.html'
})
.state('dashboard.exchange',{
templateUrl:'views/dashboard/exchange.html',
controller: 'ExchangeCtrl',
url:'/exchange/{exchangeId:[0-9]}',
})
.state('dashboard.exchange.module',{
templateUrl:'views/dashboard/exchangeModule.html',
controller: 'ExchangeModuleCtrl',
url:'/module/{exchangeModuleHostName}',
})
'/dashboard' correctly correctly routes to MainCtrl
'/dashboard/exchange/1' correctly routes to ExchangeCtrl
'/dashboard/exchange/1/module/ae38596496d3' incorrectly routes to ExchangeCtrl
Why doesn't the third url route to ExchangeModuleCtrl? How do I fix this?
In case, that we want last child state: 'dashboard.exchange.module' to totally replace the content of its parent 'dashboard.exchange', we have to options:
First option, whole parent is a target
We can place ui-view="" into the parent root <element>. There is a working example. And this would be the 'dashboard.exchange' state template views/dashboard/exchange.html:
<div ui-view="">
<h3>dashboard.exchange</h3>
<br />
context just for the state: <b>dashboard.exchange</b>
</div>
The most important is the root <div ui-view="">, because child will totally replace parent.
Second approach, target grand parent
In this case, we will skip parent. We will directly target grand parent 'dashboard'. There is a working plunker. Here we use absolute naming to target grand parent unnamed view:
.state('dashboard.exchange.module',{
views : {
'#dashboard' : {
templateUrl:'views/dashboard/exchangeModule.html',
controller: 'ExchangeModuleCtrl',
},
},
url:'/module/{exchangeModuleHostName}',
})
Check these similar Q & A for more details about absolute naming:
Angularjs ui-router not reaching child controller
Angular UI router nested views
Original part of the answer
If we want to follow standard approach - There is a working example
Your code should be workig as is.
The most important is, that each parent must contain target for a child: ui-view="", e.g.:
<div ui-view=""></div>
The view views/dashboard/main.html must contain a target for child state 'dashboard.exchange'
<div >
<h2>dashboard</h2>
<br />
<div ui-view=""></div> // this is for child exchange
</div>
The view views/dashboard/exchange.html must contain a target for child state 'dashboard.exchange.module'
<div >
<h3>dashboard.exchange</h3>
<br />
<div ui-view=""></div> // this is for child module
</div>
Check it here
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
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.
Probably it's the entire layout wrong but here is my situation, I'm using a Meanjs.org stack with Angular ui-router.
I have a layout like this:
<div data-ng-include="'/modules/core/views/header.client.view.html'"></div>
<div id="page-content" class="clearfix" fit-height>
<div id="wrap" data-ui-view="" class="mainview-animation"></div>
</div>
Now I need to reload the controller inside the header.client.view.html when I change the $state.
For example when I'm in the sign-in page and I login I need to reload the header controller, but having this it's not possible because the ui-router change only the ui-view part with the relative template:
// this change only ui-view, doesn't care about the ng-include before
state('home', {
url: '/',
templateUrl: 'modules/core/views/home.client.view.html',
});
I found the possibility to add more ui-view to the state so I could add a ui-view2 for the header instead using the ng-include but this means having the ui-view2 on each state.
Any suggest?
You might not need to "reload the controller" every time the state changes, instead make your controller react to the state change on the fly and update its properties.
Check out the ui-router $stateChangeSuccess event.
First at all you need to listen #Matti Virkkunen
It's better to listen the state in your header's controller with "$stateChangeSuccess"
So you just have to declare a controller for your header. And inside your header controller add something like this.
$scope.$on('$stateChangeSuccess', function () {
// Do what you want for example check if the current state is home with $state.is('home');
});
Do not forget to declare your controller in your template
<div data-ng-controller="HeaderController" data-ng-include="'/modules/core/views/header.client.view.html'"></div>
<div id="page-content" class="clearfix" fit-height>
<div id="wrap" data-ui-view="" class="mainview-animation"></div>
</div>