I have tried to implement angular js $state.go() with parameter. But the $state.go() works fine without parameter. But with parameter it didn't works. I already tried many examples but no way. I need to display the parameter in html view.
my state provider is,
$stateProvider
.state('home', {
url: '/',
views: {
'content#': {
templateUrl: 'content.html',
controller: 'dashCtrl'
}
},
params: {
obj: {
value:''
}
}
});
and controller is,
dashboard.controller('dashCtrl', function ($scope, $http, $state, $stateParams){
$state.go('dash_home', {obj: {value:'admin'}});
});
and my div is
<div>
<h1>welcome : {{value}} || {{obj.value}}</div>
what is the problem.?
You cannot use parameters directly in the HTML. You first have to add it to the scope (or virtual model if you use that), e.g.
$scope.obj = $state.current.params.obj
And you have to do it in the controller of the state that you are going to of course, not in those where you call $state.go
I found my mistakes. The correct code is,
$stateProvider
.state('home', {
url: '/',
views: {
'content#': {
templateUrl: 'content.html',
controller: 'dashCtrl'
}
},
params: {
value:''
}
});
controller is,
dashboard.controller('mycontroller',function($scope, $http, $state, $stateParams){
$scope.user=$state.params.registerData;
$scope.redirect=function()
{
$state.params.registerData='mycontent';
$state.go('dash_home', {registerData:$state.params.registerData});
}
});
thanks all.
I guess you can't use objects in params. Just replace
params: {
obj: {
value:''
}
}
to this:
params: {
value:''
}
and also: $state.go('dash_home', {obj: {value:'admin'}}); to $state.go('home', {value:'admin'});
Related
I am using UI-Router to navigate to detailed view. It changes state correctly and passes parameters correctly, yet the url address in the browser stays unchanged. I would like to display the passed params in the url.
app.js
'use strict';
var myApp = angular.module("myApp", ['ui.router']);
myApp.config(['$stateProvider', '$urlRouterProvider','$locationProvider',
function($stateProvider, $urlRouterProvider,$locationProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('/', {
url: '/',
templateUrl: 'partials/listView.html'
})
.state('list', {
url: '/',
templateUrl: 'partials/listView.html'
})
.state('detail', {
url: '/detail/:key',
params: {
key: { value: "" }
},
templateUrl: 'partials/detailView.html',
controller: 'DetailController'
})
// use the HTML5 History API
$locationProvider.html5Mode(true);
}]);
Controller function to go to the detail state:
myApp.controller('MainContr', [ '$scope', '$http', '$location', '$state',
'$filter','$rootScope', MainContr ]);
function MainContr($scope, $http, $location, $state, $filter,$rootScope) {
$scope.goDetailView= function(key){
console.log("trying to change url ");
// changes state correctly, and passes params to DetailController,
// but does not change browser address url.
// How can I update the url in browser here?
$state.go('detail',
{key: $scope.selectedPDFKey},
{
location:true
});
}
}
// detail view
myApp.controller('DetailController', [ '$scope', '$stateParams'
DetailController ]);
function PDFDetailController($scope,$state)
{
$scope.currentKey=$state.params.key;
}
If I remove params in $state.go('detail'), the url in browser address bar is replaced. How can I get url in browser address bar replaced as well when I pass parameters in $state.go(). Thank you.
Issue was fixed when state was changed to use query in url as:
.state('detail', {
url: '/detail?key',
params: {
key: { value: "" }
},
templateUrl: 'partials/detailView.html',
controller: 'DetailController'
})
I came across this, but in my case it was just a missing / at the beginning of the url. So this is wrong:
.state('detail', {
url: 'detail/:key',
templateUrl: 'tpl.html'
});
And this is correct/working:
.state('detail', {
url: '/detail/:key',
templateUrl: 'tpl.html'
});
I dont needed any <base> tags in my <head> at all. My application is in a subfolder called /app.
By default - UI-Router will always show the param in address bar, if is defined in the url (not just in params : {} option)
To prove it, there is a plunker with your scenario, which does what you would expect - http://plnkr.co/edit/9uBlhNoNqZsjAJEdIhYa?p=preview
Links
<a ui-sref="list">
<a ui-sref="detail({key:1})">
<a ui-sref="detail({key:22})">
A state def (as yours)
.state('list', {
url: '/',
templateUrl: 'tpl.html',
controller: 'ParentCtrl',
})
.state('detail', {
url: '/detail/:key',
params: {
key: { value: "" }
},
templateUrl: 'tpl.html',
controller: 'ChildCtrl',
});
Check it here
(you can run it in separate window, by clicking the icon in the top right corner - and see the address bar with a key param)
I got a main.html file, inside that I got a section that is visible/hidden depending on the state of a $scope.parameter. This main.html is used in two of my routes, one is the 'main' other is a sub-route. The look like this,
.state('medications', {
url: '/medications',
templateUrl: '/partials/home.html',
controller: 'mainController',
resolve: {
postPromise: ['medicationservice', function(medicationservice) {
return medicationservice.getAll();
}]
}
})
.state('medications.add', {
url: '/add',
templateUrl: '/partials/home.html',
controller: 'mainController'
})
So what I would like to do in this case is set that $scope.parameter to show this section. I have seen this examples but I don't get how I set what controller it should use.
$stateProvider.state('contacts', {
template: '<h1>{{title}}</h1>',
controller: function($scope){
$scope.title = 'My Contacts';
}
})
How do I set a parameter with explcitly setting the controller name?
Option 1:
Make it a stateParams (recommended):
.state('medications', {
params: {showSection: false},
//...
.state('medications.add', {
params: {showSection: true},
//...
And set your $scope variable in mainController to that $stateParam:
$scope.$watch($stateParams.showSection, function(){
$scope.parameter = $stateParams.showSection;
}, true);
Option 2:
Watch the $stateChangeStart event and change your $scope variable according to toState:
$scope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams){
$scope.parameter = toState === 'medications' ? false : true;
})
Use the 'data' object of $state:
.state('medications.add', {
url: '/add',
templateUrl: '/partials/home.html',
controller: 'mainController',
data: { myParameter: 'true' }
})
Then, in the controller, you can access the data using the $state service. Assign the data to the scope of the controller and you're good to go:
angular.module('myapp').controller('myController',function($scope,$state){
$scope.myParameter = $state.data.myParameter;
});
I have angular's ui-routing.
For example I have movies controller and there I have categories method and when user enter to /movies/categories I want to call this method
.state('movies', {
url: '/movies',
views: {
'pageContent': {
controller: 'movies',
templateUrl: 'movies.html'
}
}
})
How can I achieve something like this:
.state('moviesCategories', {
url: '/movies/categories',
views: {
'pageContent': {
controller: 'movies',
**method: 'categories',**
templateUrl: 'categories.html'
}
}
})
If you want to execute method on route change you can insert this code into categories.html
<div data-ng-init="categories();"> ... </div>
Better create separate controllers for each route. let's say 'categoriesController'.
$routeProvider
.when('/movie',{
templeteUrl:'templates/movies',
controller:'moviesController'
)
.when('/movies/categories',{
templeteUrl:'templates/movieCategories',
controller:'movieCategoryController',
resolve:{
categories://pull categories using a service here. inside service write $http call.
}
);
inside controller
//will inject the categories we got in reolve
angular.controller('movieCategoryController',['categories','$scope',functions(categories,$scope){
$scope.categories=categories;
}]);
in movies controler should add $state.go('moviesCategories'); this method redirect to state moviesCategories
samples in documentation
.state('state1', {
url: "/state1",
templateUrl: "partials/state1.html"
})
.state('state1.list', {
url: "/list",
templateUrl: "partials/state1.list.html",
controller: function($scope) {
$scope.items = ["A", "List", "Of", "Items"];
}
})
What I am trying to do is within the Search controller, once I get the search results back from the server ($http) change view to a different view - the search results view. I am not sure if the approach I am going about it is right, but either-way it doesn't seem to be working. I will need to pass the response as well, so the new view can display the results/response.
My app.js:
.....state('tab.search', {
url: '/search',
views: {
'tab-search': {
templateUrl: 'templates/tab-search.html',
controller: 'SearchCtrl as search'
}
}
})
.state('tab.search-results', {
url: '/results',
views: {
'tab-search-results': {
templateUrl: 'templates/tab-search-results.html',
controller: 'SearchResultsCtrl as searchResults'
}
}
})
Then my search controller has:
.controller('SearchCtrl', function($scope, $state, $location, $ionicPopup, service) {
....
$scope.doSearch = function(state) {
.....
var result = service.doSearch(dataObj);
result.then(function(response) {
console.log("I'm here");
$state.go('tab.search-results');
......
My search results view (tab-search-results.html) has the following basic code at the moment:
<ion-view view-title="Search Results">
<ion-content padding="true">
hello world
</ion-content>
</ion-view>
This basic structure is how all my other pages/views are setup too.
What happens when I perform the search is that the console message gets outputted, and then the URL changes to /results as per the tab.search-results state, but the template/view doesn't change/show.
Interestingly if I change $state.go('tab.search-results'); to point to another app state/view that I know works, it works perfectly - but for whatever reason this state/view isn't working.
Also, if there is a better way of achieving this same thing, then please let me know. I will be needing to eventually pass the "response" from SearchCtrl to SearchResultsCtrl - or rather access it on the search results page in one form or another.
Many thanks.
I think you are looking for $stateParams.
var result = service.doSearch(dataObj);
result.then(function(response) {
$state.go('tab.search-results', {'searchData':response});
}
In your routes file:
.state('tab.search-results', {
url: '/results/:searchData',
views: {
'tab-search-results': {
templateUrl: 'templates/tab-search-results.html',
controller: 'SearchResultsCtrl as searchResults'
}
}
})
And in your SearchResultsCtrl:
.controller($stateParams) {
console.log($stateParams.searchData) // will give you search results
}
NOTE:If you don't want to pass data through the URL you can use params key in the .state() method.
.state('tab.search-results', {
url: '/results',
params: {
'searchData':null
},
views: {
'tab-search-results': {
templateUrl: 'templates/tab-search-results.html',
controller: 'SearchResultsCtrl as searchResults'
}
}
})
I realised why my view wasn't changing properly. The fix was changing the views in the sub-view to reference the parent view.
Fail (sub-view has unique name from parent):
.....state('tab.search', {
url: '/search',
views: {
'tab-search': {
templateUrl: 'templates/tab-search.html',
controller: 'SearchCtrl as search'
}
}
})
.state('tab.search-results', {
url: '/results',
views: {
'tab-search-results': {
templateUrl: 'templates/tab-search-results.html',
controller: 'SearchResultsCtrl as searchResults'
}
}
})
Success (sub-view references parent, 'tab-search'):
.....state('tab.search', {
url: '/search',
views: {
'tab-search': {
templateUrl: 'templates/tab-search.html',
controller: 'SearchCtrl as search'
}
}
})
.state('tab.search-results', {
url: '/results',
views: {
'tab-search': {
templateUrl: 'templates/tab-search-results.html',
controller: 'SearchResultsCtrl as searchResults'
}
}
})
Thanks all, I think I worked out the problem. It was putting the search results page under the tab abstract state. eg: tab.search-results rather than search-results - I am guessing this was the problem as there is no search results tab. When I re-named the state to just search-results (and modified the $state.go to use 'search-results' instead of 'tab.search-results') it worked. Does this seem right?
I am trying to do what was essentially answered here Unable to open bootstrap modal window as a route
Yet my solution just will not work. I get an error
Error: [$injector:unpr] Unknown provider: $modalProvider <- $modal
My app has the ui.bootstrap module injected - here is my application config
var app = angular.module('app', ['ui.router', 'ui.bootstrap','ui.bootstrap.tpls', 'app.filters', 'app.services', 'app.directives', 'app.controllers'])
// Gets executed during the provider registrations and configuration phase. Only providers and constants can be
// injected here. This is to prevent accidental instantiation of services before they have been fully configured.
.config(['$stateProvider', '$locationProvider', function ($stateProvider, $locationProvider) {
// UI States, URL Routing & Mapping. For more info see: https://github.com/angular-ui/ui-router
// ------------------------------------------------------------------------------------------------------------
$stateProvider
.state('home', {
url: '/',
templateUrl: '/views/index',
controller: 'HomeCtrl'
})
.state('transactions', {
url: '/transactions',
templateUrl: '/views/transactions',
controller: 'TransactionsCtrl'
})
.state('login', {
url: "/login",
templateUrl: '/views/login',
controller: 'LoginCtrl'
})
.state('otherwise', {
url: '*path',
templateUrl: '/views/404',
controller: 'Error404Ctrl'
});
$locationProvider.html5Mode(true);
}])
I have reduced my controller to the following:
appControllers.controller('LoginCtrl', ['$scope', '$modal', function($scope, $modal) {
$modal.open({templateUrl:'modal.html'});
}]);
Ultimately, what I am hoping to achieve is when login is required not actually GO to the login page, but bring up a dialog.
I have also tried using the onEnter function in the ui-router state method. Couldn't get this working either.
Any ideas?
UPDATE
Ok - so as it turns out, having both ui-bootstrap.js AND ui-bootstrap-tpls breaks this - After reading the docs I thought you needed the templates to work WITH the ui-bootstrap. though it seems all the plunkers only load in the ..tpls file - once I removed the ui-bootstrap file my modal works...Am i blind? or doesn't it not really say which one you need in the docs on github? -
Now i just need to figure out how to prevent my url from actually going to /login, rather than just show the modal :)
update 2
Ok, so by calling $state.go('login') in a service does this for me.
Hi I had a hard time getting through the similar problem.
However, I was able to resolve it.
This is what you would probably need.
app.config(function($stateProvider) {
$stateProvider.state("managerState", {
url: "/ManagerRecord",
controller: "myController",
templateUrl: 'index.html'
})
.state("employeeState", {
url: "empRecords",
parent: "managerState",
params: {
empId: 0
},
onEnter: [
"$modal",
function($modal) {
$modal.open({
controller: "EmpDetailsController",
controllerAs: "empDetails",
templateUrl: 'empDetails.html',
size: 'sm'
}).result.finally(function() {
$stateProvider.go('^');
});
}
]
});
});
Click here for plunker. Hope it helps.
I'm working on something similar and this is my solution.
HTML code
<a ui-sref="home.modal({path: 'login'})" class="btn btn-default" ng-click="openModal()">Login</a>
State configuration
$stateProvider
// assuming we want to open the modal on home page
.state('home', {
url: '/',
templateUrl: '/views/index',
controller: 'HomeCtrl'
})
// create a nested state
.state('home.modal', {
url: ':path/'
});
Home controller
//... other code
$scope.openModal = function(){
$modal.open({
templateUrl: 'path/to/page.html',
resolve: {
newPath: function(){
return 'home'
},
oldPath: function(){
return 'home.modal'
}
},
controller: 'ModalInstanceController'
});
};
//... other code
Finally, the modal instance controller.
This controller synchronizes the modal events (open/close) with URL path changes.
angular.module("app").controller('ModalInstanceController', function($scope, $modalInstance, $state, newPath, oldPath) {
$modalInstance.opened.then(function(){
$state.go(newPath);
});
$modalInstance.result.then(null,function(){
$state.go(oldPath);
});
$scope.$on('$stateChangeSuccess', function () {
if($state.current.name != newPath){
$modalInstance.dismiss('cancel')
}
});
});
You may create a state with the same templateUrl and controller as your page where you want to show the modal, adding params object to it
$stateProvider
.state('root.start-page', {
url: '/',
templateUrl: 'App/src/pages/start-page/start-page.html',
controller: 'StartPageCtrl'
})
.state('root.login', {
url: '/login',
templateUrl: 'App/src/pages/start-page/start-page.html',
controller: 'StartPageCtrl',
params: {
openLoginModal: true
}
})
And in controller of the page, use this parameter to open the modal
.controller("StartPageCtrl", function($scope, $stateParams) {
if ($stateParams.openLoginModal) {
$scope.openLoginModal();
}
I found a handy hint to get this working. There are probably caveats, but it works for me. You can pass a result still but I have no need for one.
Using finally instead of the then promise resolve sorted this for me. I also had to store the previous state on rootScope so we knew what to go back to.
Save previous state to $rootScope
$rootScope.previousState = 'home';
$rootScope.$on('$stateChangeSuccess', function(ev, to, toParams, from, fromParams){
$rootScope.previousState = from.name;
})
State using onEnter
$stateProvider.state('contact', {
url: '/contact',
onEnter: function ($state, $modal, $rootScope){
$modal.open({
templateUrl: 'views/contact.html',
controller: 'ContactCtrl'
}).result.finally(function(){
$state.go($rootScope.previousState);
})
}
});