Angular StateParams never changes when Url params change? - angularjs

I am creating an Ionic app, and have a very basic routing scenario, I am trying to go to a detail page with an id param, which is optional.
Navigation occurs succesfully everytime, but when I try and access the value in the controller it remains the same as whatever the first time request was.
For e.g navigating to playlists/1 would output Object {playlistId: "1"} then when navigating to playlists/2 it would again output Object {playlistId: "1"}
I have tried so many things, but can't find the issue help appreciated.
My route setup looks like this:
.state('app.single', {
url: '/playlists/:playlistId',
views: {
'menuContent': {
templateUrl: 'templates/playlist.html',
controller: 'PlaylistCtrl',
resolve: {
playlistId: function($state, $stateParams) {
return $stateParams.playlistId; // note this changes every time. I put this here for testing.
}
}
}
}
})
And my controller:
.controller('PlaylistCtrl', function($scope, $stateParams) {
console.log($stateParams);
Navigating using:
<div class="card">
<div class="item item-text-wrap" ui-sref="app.single({playlistId: undefined})">
Test
</div>
</div>
<div class="card">
<div class="item item-text-wrap" ui-sref="app.single({playlistId: 1})">
Test 1
</div>
</div>
<div class="card">
<div class="item item-text-wrap" ui-sref="app.single({playlistId: 2})">
Test 2
</div>
</div>

It sounds like you're hitting the cache. You can disable it by adding cache:false to your state:
.state('app.single', {
cache: false, //add this
url: '/playlists/:playlistId',
views: {
'menuContent': {
templateUrl: 'templates/playlist.html',
controller: 'PlaylistCtrl',
resolve: {
playlistId: function($state, $stateParams) {
return $stateParams.playlistId; // note this changes every time. I put this here for testing.
}
}
}
}
})

Related

are these ui-sref states ie11 friendly

When trying to navigate with IE11, the links do not work with a state such as url: '/main-category/:id' but the "parent" state url: '/:main-category/' works fine. These are not true nested or parent-child since they don't actually share any common views/html template, except for navigation.
I found this meta tag suggestion and this IE events suggestion, but neither seem to be providing a solution for why my navigation bar AND links from another state do not function.
Here is a live site without minify, to test compare IE11 & all other browsers.
So, are these routes correctly setup?
router.js
angular.module('app_litsco')
.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', function ($stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', { //this state works
url: '/',
templateUrl: 'html/home.html',
controller: 'controller_home',
})
.state('product_streamline', { //this state DOES NOT work
url: '/streamline_metal_panels/:id',
templateUrl: 'html/template_product.html',
controller: 'controller_prods',
})
.state('streamline_panels', { //this state works
url: '/:cat',
templateUrl: 'html/template_productlist.html',
controller: 'controller_productlist',
})
$locationProvider.html5Mode(true);
}]);
index.html
example NavBar section
<li class="link">
<!-- Main Category link -->
<a data-activates="streamline-panel-dropdown" class="blue-text text-darken-4 product-link" ui-sref="streamline_panels({ cat: 'streamline_metal_panels' })">STREAMLINE METAL PANELS</a>
<div id="streamline-panel-dropdown" class="dropdown-content dropdown-full full">
<div class="container dropdown-container flex-row-around-center">
<div class="col sm12 m3 text-center dropdown-item">
<!-- Sub-Category links -->
<a ui-sref="product_streamline({ id: 'classic_cr' })" class="product-link">Classic CR</a>
</div>
<div class="col sm12 m3 text-center dropdown-item">
<a ui-sref="product_streamline({ id: 'omniwall_md' })" class="product-link">Omniwall MD</a>
</div>
<div class="col sm12 m3 text-center dropdown-item">
<a ui-sref="product_streamline({ id: 'omniwall_cl' })" class="product-link">Omniwall CL</a>
</div>
</div>
</div>
</li>
Your product_streamline state uses Array.find() in a resolve, which IE doesn't support.
.state('product_streamline', {
url: '/streamline_metal_panels/:id',
templateUrl: 'html/template_product.html',
controller: 'controller_prods',
resolve: {
product: ['factory_litsco', '$stateParams', function (factory_litsco, $stateParams) {
var productIdObj = factory_litsco.find(function (obj) {
if (obj.id === $stateParams.id) {
return obj;
}
});
return productIdObj;
}],
$title: ['product', function (product) {
return product.productName;
}]
}
})
To detect these sort of errors, add a handler for $stateChangeError such as:
angular.element(document.getElementsByTagName('body')[0]).scope().$on('$stateChangeError', function() { console.log("Error", arguments) } )

ui-sref not working state angularjs

I'm working on something and I want to redirect the content to a page in angularjs, but I face the following error:
angular.js:12477 Error: Could not resolve 'dashboard.home' from state 'dashboard'
My code:
.state(
'dashboard.home',
{
url: '/home',
views: {
"content#main": {
templateUrl: '/home'
// controller: 'HomeController',
}
}
}
)
.state(
'dashboard',
{
url: '',
parent: "main",
views: {
"sidebar#main": {
templateUrl: "/sidebar/view"
}
}
})
sidebar.html.twig
<li>
<a ui-sref="dashboard.home">Home <span class="sr-only">(current)</span></a>
</li>
The state 'dashboard.home' exists, why the error appears?
I think you're probably trynig to use views to split header/footer/siderbar from the content which is the only thing to change according states.
I don't have the answer of what exactly is your problem but I may have an answer to a more broader question that you might are trying to solve :
How to mix views for header/content/footer and nested stated for content navigation ?
Solution : use views only for header/content/footer, use '#' to insert direct child by using the default view (no name) and use grand child as you would do normally without views
// root state
.state('home', {
url:'/home',
views:{
'header':{
templateUrl: 'template/header.html',
controller:'HeaderCtrl'
},'sidepanel':{
templateUrl: 'template/sidepanel.html',
controller:'SidePanelCtrl',
},'footer':{
templateUrl: 'template/footer.html'
}
},
'abstract':false
})
//direct child
.state('home.main', {
url:'/main',
// need that for every direct child of home
views:{
'#':{templateUrl: 'template/main.html',
controller: 'MainCtrl'
}
}
})
//grandchild
.state('home.main.child1', {
url:'/child1',
templateUrl: 'template/child1.html',
controller: 'Child1Ctrl'
// NO view anymore for grand child!!
}
})
And the Relevant HTML
<section id="header">
<!--- not container -->
<div data-ui-view="header"></div>
</section>
<section id="content">
<div class="row clearfix">
<div id="mySidebar>
<div data-ui-view="sidepanel"></div>
</div>
<div id="myContent">
<div data-ui-view></div>
</div>
</div>
</section>
<section id="footer">
<div data-ui-view="footer"></div>
</section>
The templateUrl expects the relative path of the html template that you want to render.
.state(
'dashboard.home',
{
url: '/home',
views: {
"content#main": {
templateUrl: 'home.html'
}
}
}).state(
'dashboard',
{
url: '',
parent: "main",
views: {
"sidebar#main": {
templateUrl: "sidebar/view.html"
}
}
})

AngularJS $stateprovider

I am new to angularjs, I am not able to understand the concept of $stateprovider
I want to create a header that has menu and logo and the body content should change when clicked on menu items accordingly, code is given below, please check and answer my query
HTML
<div ui-view = "header"></div>
<div ui-view = "content"></div>
JS
var App=angular.module('test', ["ui.router", "App.controllers", "ui.bootstrap"]);
App.config(function ($stateProvider){
$stateProvider
.state('test', {
url: '',
views: {
'header': { templateUrl: '/templates/header.html'}
}
});
})
Thank You
Since you have taken two views, one for header and other for content,
<div ui-view = "header"></div>
<div ui-view = "content"></div>
The route also should have two different named routes.
views: {
'header': { templateUrl: '/templates/header.html'},
'content': { templateUrl: '/templates/content.html'}
}
From this,
<div ui-view = "header"></div> opens header.html and <div ui-view = "content"></div> opens content.html
Here is the code,
var App=angular.module('test', ["ui.router", "App.controllers", "ui.bootstrap"]);
App.config(function ($stateProvider){
$stateProvider
.state('test', {
url: '',
views: {
'header': { templateUrl: '/templates/header.html'},
'content': { templateUrl: '/templates/content.html'}
}
});
})
In the HTML,
<ul class="nav nav-pills main-menu right">
<li role="presentation"><a ui-sref="test" class="active">Home</a></li>
<li role="presentation">Bus Chart</li>
<li role="presentation">My Bookings</li>
<li role="presentation">Reviews</li>
<li role="presentation">Contact</li>
</ul>
The first li click goes to our test state as given in routes.
Here is the documentation for the same
In config File
// State definitions
$stateProvider
.state('test', {
abstract: true,
views: {
'main#': {
templateUrl: 'app/../../full-view.html'
},
'header#test': {
templateUrl: '/templates/header.html' // correct path to the template
// controller: 'HeaderController as vm' if needed
},
'footer#test': {
templateUrl: '/templates/footer.html' // correct path to the template
// controller: 'FooterController as vm' if needed
}
}
});
HTML
in content-only.html
<div>
<div ui-view = "content"></div>
</div>
in full-view.html
<div class="container">
<div ui-view="header"></div>
<div>
<div ui-view="content"></div>
</div>
<div ui-view="footer"></div>
</div>
in index.html
<body>
<div ui-view="main"></div>
</body>
in other modules(example)
views: {
'content#test': {
templateUrl: 'app/main/policies/policies.html'
// controller: 'PoliciesController as vm' if needed
}
}
so that whatever you append to content#test will comes under ui-view="content"
for routing avoid using href="", use ui-sref="" since you are using ui-router
example ui-sref="app.home" or ui-sref="app.about" rather than usinghref="#/home" or href="#/about"

If ui state provider redirect to particular template and in that I have to check authentication & need to redirect to dashboard

If ui state provider redirect to particular template and in that I have to check authentication if its ng-switch-when=true need to redirect to dashboard
Below is my state provider configuration. and below is my mail.html.
on click on home page I need to check if the user logged in then redirect to dashboard.html template, Is it possible to do it in resolve method ?.
angular.module('sample')
.config(function ($stateProvider) {
$stateProvider
.state('home', {
parent: 'site',
url: '/',
data: {
roles: []
},
views: {
'content#': {
templateUrl: 'scripts/app/main/main.html',
controller: 'MainController'
}
},
resolve: {
}
});
});
<div ng-cloak>
<div class="row">
<div class="col-md-12 text-center">
<h3>Welcome to Admin portal!</h3>
<div ng-switch="isAuthenticated()">
<div class="alert alert-success" ng-switch-when="true">
You are logged In.
</div>
<div class="alert alert-warning" ng-switch-when="false">
If you want to Login
</div>
</div>
</div>
</div>
</div>
Yes you can apply the same in resolve. Define the function isAuthenticated() in resolve and check you condition there and return true/false as you want.
angular.module('sample')
.config(function ($stateProvider) {
$stateProvider
.state('home', {
parent: 'site',
url: '/',
data: {
roles: []
},
views: {
'content#': {
templateUrl: 'scripts/app/main/main.html',
controller: 'MainController'
}
},
resolve: {
isAuthenticated : function () {
//get your condiion here for checking iff user is logged in
if(logged in )
return true
else
return false
}
}
});
});

AngularJS : How do I nest a view within a parent state with parameters?

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>

Resources