I'm using Angular ui route and I'm trying to pass query parameters but it doesn't work. I have followed the official wiki.
In the view I have the following code very simple
<div ng-controller="MainController">
<a ng-href="#/foo/bar?param={{make}}"><li>{{make}}</li></a>
</div>
and this is the config
function config($stateProvider, $urlRouterProvider) {
$stateProvider
.state('foo', {
url: '/foo',
templateUrl: '/partials/foo.html',
controller: 'MainController'
})
.state('foo.bar', {
url: '/bar?param',
templateUrl: 'partials/foo.bar.html',
controller: 'SecondaryController'
});
}
but when I click on the link in the view the url I get it is what I get but the route doesn't receive the request.
Use ui-sref directive to generate href link
Markup
<div ng-controller="MainController">
<a ui-sref="foo.bar({param: make})"><li>{{make}}</li></a>
</div>
Related
I have nested states inside neste state here is controller definition:
(function () {
"use strict";
angular.module("gameManagement", ["ui.router", "ngAnimate", "ngResource", "toaster"])
.config(["$stateProvider", "$urlRouterProvider", function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/game/MultiStepForm/step1");
$urlRouterProvider.otherwise("/game/Home");
$stateProvider
.state("Home", {
url: "/game/Home",
templateUrl: "/app/game/GameView.html",
controller: "GameController",
controllerAs: "vm"
});
$stateProvider
.state("Log", {
url: "/Game/Log",
templateUrl: "/app/Log/GameLogView.html",
controller: "GameLogController",
controllerAs: "vm"
});
$stateProvider
.state("MultiStepForm.view", {
url: "/Game/MultiStepFormView",
templateUrl: "/app/MultiStepForm/MultiStepFormView.html",
controller: "MultiStepFormViewController",
controllerAs: "MultiStepViewLogic"
})
$stateProvider
.state("MultiStepForm.Edit", {
url: "/Game/MultiStepFormEdit",
templateUrl: "/app/MultiStepFormEdit/MultiStepForm.html",
controller: "MultiStepFormEditController",
controllerAs: "MultiStepEditLogic"
})
.state('MultiStepForm.Edit.step1', {
url: '/step1',
templateUrl: '/app/MultiStepForm/NestedViews/FormStep1.html'
})
.state('MultiStepForm.Edit.step2', {
url: '/step2',
templateUrl: '/app/MultiStepForm/NestedViews/FormStep2.html'
})
.state('MultiStepForm.Edit.step3', {
url: '/step3',
templateUrl: '/app/MultiStepForm/NestedViews/FormStep3.html'
});
}]);
})();
This rows define multi-step form:
.state('MultiStepForm.Edit.step1', {
url: '/step1',
templateUrl: '/app/MultiStepForm/NestedViews/FormStep1.html'
})
.state('MultiStepForm.Edit.step2', {
url: '/step2',
templateUrl: '/app/MultiStepForm/NestedViews/FormStep2.html'
})
.state('MultiStepForm.Edit.step3', {
url: '/step3',
templateUrl: '/app/MultiStepForm/NestedViews/FormStep3.html'
});
Here is view of MultiStepForm.Edit state:
<!-- form.html -->
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<div id="form-multiple-step">
<div class="page-header text-center">
<!-- the links to our nested states using relative paths -->
<!-- add the active class if the state matches our ui-sref -->
<div id="status-buttons" class="text-center">
<a ui-sref-active="active" ui-sref="MultiStepForm.Edit.step1"><span>STEP1</span></a>
<a ui-sref-active="active" ui-sref="MultiStepForm.Edit.step1"><span>STEP2</span></a>
<a ui-sref-active="active" ui-sref="MultiStepForm.Edit.step1"><span>STEP3</span></a>
</div>
</div>
<form id="single-form">
<!-- our nested state views will be injected here -->
<div id="form-views" ui-view></div>
</form>
</div>
</div>
</div>
When MultiStepForm.Edit state activated no netsed view has been displayed they have been display only when the user press button in view form and UI-SREF activate appropriate state.
My question is how can I make MultiStepForm.Edit.step1 state display associated view by default when MultiStepForm.Edit state activated?
The most simple way here would be to use the $urlRouterProvider.when()
$urlRouterProvider.when("/game/MultiStepForm", "/game/MultiStepForm/step1");
Check the doc:
when(what, handler)
Registers a handler for a given url matching. if handle is a string, it is treated as a redirect, and is interpolated according to the syntax of match (i.e. like String.replace() for RegExp, or like a UrlMatcher pattern otherwise).
If the handler is a function, it is injectable. It gets invoked if $location matches. You have the option of inject the match object as $match.
The handler can return
falsy to indicate that the rule didn't match after all, then $urlRouter will continue trying to find another one that matches.
string which is treated as a redirect and passed to $location.url()
void or any truthy value tells $urlRouter that the url was handled.
I'm using the Ionic Framework to create a mobile app, but I'm having a difficult time with the UI Router. I've gotten a few screens working properly, but I can't seem to get nested views working on a state with parameters. I'd like a URL that looks like /legislator/1/profile. It would have a header with the name of legislator #1 and tabs below. The profile tab would be automatically visible and clicking on other tabs (e.g. /legislator/1/votes) would change the content, but not the header
I wound up abandoning the tabs & sidemenu starter projects to customize my nested views. Here's what I have in app.js. The home and people.* states work correctly, but I can't seem to load the legislator screen with the profile view in place. I've tried changing the abstract & controller attributes, but no luck yet.
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: "/home",
templateUrl: "templates/home.html",
controller: "homeController"
})
.state('people', {
url: "/people",
abstract: true,
templateUrl: "templates/people.html"
})
.state('people.legislators', {
url: "/legislators",
templateUrl: "templates/legislators.html",
controller: "legislatorController"
})
.state('people.following', {
url: "/following",
templateUrl: "templates/following.html",
controller: "followingController"
})
.state('legislator', {
url: "/legislator/{legislatorId:int}",
templateUrl: "templates/legislator.html",
abstract: true
})
.state('legislator.profile', {
url: "/legislator/{legislatorId:int}/profile",
templateUrl: "templates/legislator.profile.html",
controller: "profileController"
})
.state('legislator.votes', {
url: "/legislator/{legislatorId:int}/votes",
templateUrl: "templates/legislator.votes.html",
controller: "votelistController"
})
$urlRouterProvider.otherwise('/home');
// if none of the above states are matched, use this as the fall-back
})
How is this scenario supposed to work in the UI Router? Once I have $stateProvider configured, how should the tabs link to the nested states?
Thanks for any help you can give me.
Maybe your solution is as simple as replacing the classic href by Ui Router's ui-sref:
replace
<ion-tab ... href="#/legislator/{ scopeLegislatorId }/profile">...</ion-tab>
by
<ion-tab ... ui-sref="legislator.profile({ legislatorId: scopeLegislatorId })">...</ion-tab>
Where scopeLegislatorId is the legislatorId, available from your scope.
If that doesn't help, please provide us with your html files (e.g. legislator.html and legislator.profile.html).
You can use following method to create separate views.
state('people.following',{
data:{
anyVar: {
label: 'cp',
text : 'anyText'
}
},
views: {
'content#people': angularAMD.route({
template: infoView,
controller: 'custInfoCtrl',
controllerUrl: 'modules/custCtrl'
}),
'mobileView#people': angularAMD.route({
template: mobileView,
controller: 'mobileCtrl',
controllerUrl: 'modules/mobileBottomViewCtrl'
})
}
})
<pre>
<div ui-view='contentArea'> </div>
<div ui-view='mobileView'> </div>
</pre>
RobYed pointed me in the right direction to figure out the right way to define my states. Here's the bones of what I wound up with.
app.js:
.state('legislator', {
url: "/legislator",
templateUrl: "templates/legislator.header.html",
abstract: true,
})
.state('legislator.profile', {
url: "/{seq_no:int}/profile",
templateUrl: "templates/legislator.profile.html",
controller: "profileController"
})
templates/legislator.header.html:
<ion-nav-view animation="slide-left-right">
<div class="bar bar-header" ng-controller="profileController">
{{legislator.name}}
</div>
<div class="tabs tabs-striped tabs-top">
<a class="tab-item" ui-sref="legislator.profile" ng-class="{selected: is('legislator.profile')}">
{{'Profile' | translate}}
</a>
<a class="tab-item" ui-sref="legislator.votes" ng-class="{selected: is('legislator.votes')}">
{{'Votes' | translate}}
</a>
<a class="tab-item" ui-sref="legislator.stats" ng-class="{selected: is('legislator.stats')}">
{{'Stats' | translate}}
</a>
</div>
<div ui-view></div>
</ion-nav-view>
templates/legislator.profile.html:
<ion-content>
<div class="bar bar-stable has-subheader" style="height:145px;">
{{legislator.whatever}}
Content Here
</div>
</ion-content>
profileController.js:
'use strict';
angular.module('myApp').controller('profileController', function($scope, $rootScope) {
$scope.legislator = $rootScope.legislators[$stateParams.seq_no-1];
});
Links from other states:
<a ui-sref="legislator.profile({seq_no:legislator.seq_num})"></a>
I'l try to use AngularJs with ui.router, but have the trouble.
This example have three states: index, template and template.show
$stateProvider
.state('/', {
url: '',
template: '<a ui-sref="template">GoTo Template Index</a>'
})
.state('template', {
url: 'template',
templateUrl: 'template_index.html',
controller: 'TemplateCtrl'
})
.state('template.show', {
url: '/{templateId:[0-9]+}',
templateUrl: 'template_show.html',
controller: 'TemplateShowCtrl'
})
Please, see plunker: http://plnkr.co/edit/prluQs9vXeJw9IVi2JYW?p=info
But only two first states working. State "template.show" changing, loading template, but does not execute TemplateShowCtrl and not update ui-view to new template.
You can see screenshot
Any child state requires the presence of a subsequent ui-view directive in its parent so that it knows where to insert the html. Currently, there is not one present in the template_index.html markup.
It should instead look something akin to this:
<ul>
<li ng-repeat="t in templates">
<a ui-sref="template.show({templateId:t.id})" href='#'>
{{t.name}}
</a>
</li>
</ul>
<!-- target element -->
<ui-view></ui-view>
I have a link in an angular app that looks like this:
<tab ng-controller="childCtrl" heading="Children">
edit
</tab>
How can I load the link inside the tab instead of refreshing the entire view?
I like other approach with one point of handling all routes. ui.router with nested views allows to do it.
Template
<div ><a ui-sref="home.tab1" >Tab1</a></div>
<div><a ui-sref="home.tab2" >Tab2</a></div>
<br>
<div ui-view="tabs"></div>
app
var app = angular.module('plunker', ['ui.router']);
app.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'main.html',
controller: 'MainCtrl',
virtual: true
})
.state('home.tab1', {
url: '/tab1',
views: {
tabs: {
templateUrl: '1.html'
}
}
})
.state('home.tab2', {
url: '/tab2',
views: {
tabs: {
templateUrl: '2.html'
}
}
});
$urlRouterProvider
.otherwise('/home/tab1');
})
And demo http://plnkr.co/edit/r1jPgkMnPAMlI34gZrMA?refresh&p=preview
You could define the path to the selected tab's content when the link is clicked, and use ng-include to display it.
<div ng-repeat="parent in parents">
<div ng-repeat="child in parent.children">
<a href="" ng-click="selectPath(parent, child);">
Parent {{parent.Id}}, Child {{child.Id}}
</a>
</div>
</div>
<div ng-include="selected.path"></div>
Here is a demo: http://plnkr.co/edit/7SPnluxUfcNNQDyeC6yt?p=preview
I have the following code in my app.js:
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'app/login/login.html'
})
.state('admin', {
url: '/admin',
templateUrl: 'app/admin/layout/layout.html',
abstract: true
})
.state('admin.dashboard', {
url: '',
templateUrl: 'app/admin/dashboard/dashboard.html'
})
.state('admin.client', {
url: '/client',
templateUrl: 'app/admin/client/client.html',
controller: 'ClientController',
})
.state('admin.client.new', {
url: '/client/new',
templateUrl: 'app/admin/client/new.html',
controller: 'ClientController',
})
Then, on layout.html I have this:
<section class="content" ui-view></section>
Which loads the admin.dashboard by default. And from there I have a link to load the admin.client
It's fine. But the problem comes in my client.html. I got the following:
<a ui-sref=".new">
<button class="btn btn-app">
<i class="ion ion-plus"></i> New Client
</button>
</a>
What I expect it to do is to change the ui-view in layout.html from client/client.html to client/new.html but nothing happens.
If I add an ui-view tag inside client.html then the new.html is loaded there. But I need it to load on ui-view of layout.html.
If you use the attribute ui-view without specifying view name like ui-view="myviewname", stateProvider is matching the view hierarchy (the nested ui-view attributes) to your state hierarchy. So its expecting to find the target ui-view in client.html, like you found out yourself.
Change the state name 'admin.client.new' to 'admin.newclient', and your ui-sref link to 'admin.newclient'. Maybe that's what you want.
StrangeLoop's answer worked but I found a better solution.
I added the parent parameter to the new client state. Now it looks like:
.state('admin.client.new', {
parent: 'admin',
url: '/client/new',
templateUrl: 'app/admin/client/new.html',
controller: 'ClientController',
})
And on client.html:
<a ui-sref="admin.client.new">
<button class="btn btn-app">
<i class="ion ion-plus"></i> Novo Cliente
</button>
</a>