I'm making the transition from NgRoute to ui-router using angular 1.0.8. Due to the fact I had some nested views I had to reload the routes which worked fine with ngRoute. I'm having the same issue with ui-router, is there an equivalent method I can use for this at all?
I'm using ui-router 0.2.10.
Edit:
I've created a fiddle to illustrate the issue that I'm having loading a basic view using ui-router.The view is requested and I can see it in the network inspector. The thing I can get my head around is why the view in not being injected into the template.
What am I missing here?
.run(function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
});
You are looking for the reload() function:
$state.reload()
http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state
You would put this in a controller like so:
var app angular.module('app', ['ui.router']);
app.controller('ctrl', function ($scope, $state) {
$scope.reload = function(){
$state.reload();
}
});
Edit 1
This is wrong.
.run(function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
});
You just need to inject $state into the controller you want to use it in.
angular.module('app').controller('Ctrl', ['$scope', '$state', function($scope,$state)
// Use $state here
$state.go('stateName');
{}]);
You forgot to inject ui.router, do that and it works fine.
https://jsfiddle.net/Christian_Schiffer/wLybswL9/1/
var myapp = angular.module('myapp', ['ui.bootstrap', 'ui.router']).config(function ($stateProvider, $urlRouterProvider) {
$stateProvider.state('one', {
url: '/',
templateUrl: '/one.html',
controller: 'MyCtrl'
})
$urlRouterProvider.otherwise('/');
}).run(function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
});
myapp.controller('MyCtrl', function ($scope) {
$scope.templateUrl = '/mobileTemplate.html';
});
myapp.controller('AccordionDemo', function ($scope) {
$scope.groups = [{
title: "Dynamic Group Header - 1",
routePath: "one.html",
number: 1,
current: true
}, {
title: "Dynamic Group Header - 2",
routePath: "two.html",
number: 2,
current: false
}];
});
Related
I am facing problem in call to controller in child ui state router.
URL is changing but controller not call.
no console error*
Please check code:
HTML
<a style="cursor: pointer;" class="btn btn-default btn-xs" ui-sref="interactions.details({id:n.id})">Detail</a>
Router
.state('interactions', {
url: '/interactions',
data: {
pageTitle: 'Interaction',
IsLoginPage: false
},
templateUrl: '../../modules/interaction/views/interaction.html',
controller: 'interactionCtl'
})
.state('interactions.details', {
url:'/details/:id',
data: {
pageTitle: 'Interaction Details',
IsLoginPage: false
},
templateUrl: '../../modules/interaction/views/interactionDetail.html',
controller:'interactionCtlDetails'
}).run(function ($rootScope, settings, $cookies, $http, $location, AuthenticationService, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
});
Controller
warApp.controller('interactionCtlDetails', ["$scope", '$rootScope','$stateParams', 'settings', 'categoryService', 'blockUI',
function ($scope, interactionService, $rootScope, $stateParams ,settings, categoryService, blockUI) {
var id = $stateParams.id;
console.log(id);
});
Annotation array should be in sync with the parameters in the function declaration.Here annotation array is not in sync with the parameters in the function declaration.
Second parameter in your annotation array is 'interactionService' but in function, thats 'rootScope'.
Try with below controller code
warApp.controller('interactionCtlDetails', ['$scope', '$rootScope', '$stateParams', 'settings', 'categoryService', 'blockUI',
function ($scope, $rootScope, $stateParams ,settings, categoryService, blockUI) {
var id = $stateParams.id;
console.log(id);
});
warApp.controller('interactionCtlDetails', ["$scope", '$rootScope','$stateParams', 'settings', 'categoryService', 'blockUI',
function ($scope, interactionService, $rootScope, $stateParams ,settings, categoryService, blockUI) {
var id = $stateParams.id;
console.log(id);
});
In above code you have function ($scope, interactionService, $rootScope, $stateParams ,settings, categoryService, blockUI) where you have interactionService which you have missed in your injection section
Simpler example of routing, maybe you can narrow down the problem by adding one controller at a time and build the rest. Fiddle or error will help.
angular.module('myApp').config(function ($stateProvider){
$stateProvider
.state('form', {
url:"/form",
views: {
"listColumn": {
templateUrl: "/form1.html",
controller:'myController1'
},
"formColumn": {
templateUrl: "/form2.html"
}
}
})
});
Definitely your controller should throw an error in console, the order of dependency parameters injected in the controller is wrong, you are missing interactionService
change it as,
warApp.controller('interactionCtlDetails', ["$scope", 'interactionService','$rootScope','$stateParams', 'settings', 'categoryService', 'blockUI',
function ($scope, interactionService, $rootScope, $stateParams ,settings, categoryService, blockUI) {
});
edit: I'm using bootstrap, I think bootstrap tab is causing the
problem
View does not get updated after $scope variable update.
$scope.codeData
if i console the $scope.codeData, i can see the data, but does not render in view.
I have to click twice to get the view render correctly.
is there anything wrong with my code??
Thank you.
config
angular.module('SPAroutes', ['ngRoute', 'SPAcontrollers', 'SPAdirectives'])
.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider
.when('/admin', {
templateUrl: 'templates/views/admin.html',
controller: 'adminCtrl',
controllerAs: 'admin'
})
$locationProvider.html5Mode(true).hashPrefix('!');
}]);
Controller.js
angular.module('SPAcontrollers', ['ngRoute', 'SPAfactories', 'SPAdirectives']).controller('adminCtrl', ['$scope', '$http', '$location', '$window', '$SPAaccount', function ($scope, $http, $location, $window, $SPAaccount) {
this.dataRetrive = function(category){
$http.get('/ctrls/get/blockCode/header').then(function (res){
$scope.codeData = res.data;
console.log($scope.codeData);
$('#headerTab').tab('show');
}, function (err){
console.log(err);
})
};
}]);
admin.html
{{codeData}}
You are mixing up controllerAs with scope as phil mentioned in his comment on question. Instead of using scope here store values insidethis reference something like this.
angular.module('SPAcontrollers', ['ngRoute', 'SPAfactories', 'SPAdirectives']).controller('adminCtrl', ['$scope', '$http', '$location', '$window', '$SPAaccount', function ($scope, $http, $location, $window, $SPAaccount) {
var admin = this;
this.dataRetrive = function(category){
$http.get('/ctrls/get/blockCode/header').then(function (res){
admin.codeData = res.data;
console.log(admin.codeData);
$('#headerTab').tab('show');
}, function (err){
console.log(err);
})
};
}]);
and inside the view: admin.html
{{admin.codeData}}
here is working plunk for your refernce
I am using a module where I add in my first controller which is taking a service as a dependency. All the service is doing is bringing in some data.
Then I have a show function which I am adding on an anchor element in my view in order to be able to click on the the first name and then get the user's details.
My second controller takes the data from the first controller and then using $routeParams I am trying to show the data on the user view.
Is there something I am doing wrong here?
(function() {
var app = angular.module('test');
app.controller('testCtrl', ['$scope', 'testFactory', '$location', function($scope, testFactory, $location) {
testFactory.getContact().then(function(data) {
$scope.contacts = data.data;
});
$scope.show = function(firstname) {
$location.path('main/' + firstname);
};
}]);
app.controller('userCtrl', ['$scope', '$routeParams', function($scope, $routeParams) {
$scope.user = $scope.contacts[$routeParams.firstname];
}]);
}());
These are the routes
(function() {
var app = angular.module('test', ["ngRoute"]);
app.config(function($routeProvider, $locationProvider) {
$routeProvider
.when("/main", {
templateUrl: "main.html",
controller: "testCtrl"
})
.when("/main/:firstname", {
templateUrl: "contact.html",
controller: "userCtrl"
})
.otherwise({redirectTo:"/main"});
$locationProvider.html5Mode(true);
});
}());
This is the error I am getting in my console:
TypeError: Cannot read property 'any1' of undefined
where any1 is the is the first name.
I've seen all the other answers for similar questions but I think this is different.
I have a state defined as such:
.state('2col.flight-log', {
url: 'flight-log',
templateUrl: 'components/2col-pages/flight-log/flight-log.html',
data : { pageTitle: 'Flight Log' }
})
Within flight-log.html I'd like to do something like {{$state.current.data.pageTitle}} or {{$state.data.pageTitle}}. However, this doesn't work. Am I doing something wrong?
I understand the state change issue inherent with this approach but this is fine for now. If I have to create a directive I will, but it really seems like overkill. Should the way I've outlined work?
Here's how I got it working:
app.run([ '$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}])
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
app.state('2col.flight-log', {
url: 'flight-log',
templateUrl: 'components/2col-pages/flight-log/flight-log.html',
data : { pageTitle: 'Flight Log' }
})
and in flight-log.html I put {{$state.current.data.pageTitle}} wherever I needed it.
What's important about this is the app.run block. From the documentation "A run block is the code which needs to run to kickstart the application. It is executed after all of the service have been configured and the injector has been created."
This is how I do it:
Set at $rootScope a ref to $state in app.run
var app = angular.module('app', ['ui.router']);
app.run(['$rootScope', '$state', '$stateParams',
function($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}
]);
app.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$urlRouterProvider
.otherwise('/');
$stateProvider
.state("home", {
url: "/",
template: 'HELLO WORLD',
data: {
myData: "Working!"
}
});
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
<script src="https://cdn.jsdelivr.net/angular.ui-router/0.2.10/angular-ui-router.js"></script>
<pre ng-app="app" id="uiRouterInfo">
$state = {{$state.current.name}}
$stateParams = {{$stateParams}}
$state full url = {{ $state.$current.url.source }}
$state my data = {{ $state.$current.data.myData }}
</pre>
I have the following HTML:
<!doctype html>
<html lang="en" ng-class="theme">
<head>
...
</head>
<body>
<form>
<button class="white-gradient glossy" ng-click="theme = 'darkBlue'">Blue</button>
<button class="white-gradient glossy" ng-click="theme = 'black'">Black</button>
</form>
#Scripts.Render("~/bundles/Angular")
<script type="text/javascript">
angular.element(document).ready(function () {
angular.bootstrap(angular.element(document).find('html'), ['app']);
});
</script>
</body>
</html>
The buttons act as theme switchers to change my CSS and this works fine.
Here's my app.js
var app = angular
.module('app', ['ui.router', 'admin', 'home', 'questions', 'ngResource', 'LocalStorageModule'])
.config(['$locationProvider', '$sceProvider', '$stateProvider',
function ($locationProvider, $sceProvider, $stateProvider) {
$sceProvider.enabled(false);
$locationProvider.html5Mode(true);
var home = {
name: 'home',
url: '/home',
views: {
'menu': {
templateUrl: '/Content/app/home/partials/menu.html',
},
'content': {
templateUrl: '/Content/app/common/partials/empty.html',
}
}
}
$stateProvider
.state(home));
}])
.run(['$rootScope', '$scope', '$state', '$stateParams', function ($rootScope, $scope, $state, $stateParams) {
$scope.theme = 'darkBlue'
}])
.controller('appController', ['$scope', '$resource', '$state', function ($scope, $resource, $state) {
$scope.state = $state;
}]);
I am trying to set the default theme (line 2 of the HTML) at startup to 'darkBlue'.
However this does not seem to work. When my application starts the theme is not defined.
Can someone tell me what I am doing wrong and why it seems to ignore the line $scope.theme = 'darkBlue' ?
Note I also tried the following and this does not set the theme either:
.run(['$rootScope', '$state', '$stateParams', function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$state.transitionTo('home')
}])
.controller('appController', ['$scope', '$resource', '$state', function ($scope, $resource, $state) {
$scope.state = $state;
$scope.theme = 'darkBlue'
}]);
In your original example, you're injecting $scope into the run function
.run(['$rootScope', '$scope', '$state', '$stateParams', function ($rootScope, $scope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$state.transitionTo('home')
$scope.theme = 'darkBlue'
}])
but run cannot inject $scope because it isn't run against any particular view or controller. You can, however, inject $rootScope (as you already are) and set the data there:
.run(['$rootScope', '$scope', '$state', '$stateParams', function ($rootScope, $scope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$state.transitionTo('home')
$rootScope.theme = 'darkBlue'
}])
Prototypal inheritance will ensure that theme is available as a property on any child scope; however, you won't be able to change that value, because in JavaScript, writing to a property in this manner overwrites the property on the child object (e.g. setting $scope.theme in a controller would not propogate the change back up to the $rootScope, as you saw in your second example). See this wiki article for more information.
What you would most likely want to do is create a service to serve as the shared state between all the various places you want to access and change the data. You can find more information about services in the Developer Guide and as a video tutorial on egghead.io, but basically you can inject them into any number of controllers and the controllers share a single instance of the service. For example, it may look something like this:
<body>
<div ng-controller="ThemeController">
<form>
<button class="white-gradient glossy"
ng-click="theme.set('darkBlue')">Blue</button>
<button class="white-gradient glossy"
ng-click="theme.set('black')">Black</button>
</form>
</div>
#Scripts.Render("~/bundles/Angular")
#Scripts.Render("~/bundles/AngularApp")
<script type="text/javascript">
angular.element(document).ready(function () {
angular.bootstrap(angular.element(document).find('html'), ['app']);
});
</script>
</body>
Then, you can set up your service and inject it into controllers:
var app = angular
.factory('theme', function() {
var theme = null;
// every time you inject `theme`, it will inject the same instance
// of this object, which contains methods for getting and setting
// the current theme
return {
get: function() { return theme; },
set: function(t) { theme = t; }
};
})
// we can set the default theme in a `run` function
// by injecting it
.run(function(theme) {
theme.set('darkBlue');
})
// Here is the new `ThemeController` we created in the template, above
.controller('ThemeController', function($scope, theme) {
// bind `theme` to the scope so we can change it
$scope.theme = theme;
})
.config( // rest of app config
Working example: http://jsfiddle.net/BinaryMuse/bnAzp/