Angular - ng-class based on state - angularjs

Any specific reason why my code is not working?
<li ng-class="{active : $state.includes('products')}">
router code:
.state('products', {
url: '/products',
templateUrl: 'app/components/views/products/products.html',
controller: 'productsController',
controllerAs: 'products'
})

You are forgetting to set the $state and $stateParams on your $rootScope, if you do so, you can keep using your first approach on html:
angular.module("myApp").run(function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
});
This way you don't need to inject them on every single controller.
Here is the reference:
https://github.com/angular-ui/ui-router/wiki/quick-reference#note-about-using-state-within-a-template
PS: I personally don't recommend this kind of global approach, but it has its merits

you will need to get the $state provider via the $injector in your controller (as you would inject yourself $scope or a service.
EDIT:
Include it as such:
angular.module('yourModule', []).controller('YourController',['$injector',
funciton($injector){}
]);
Then:
$scope.$state = $injector.get('$state');
You now have access to $state. To get the name of your current state, simply use:
$state.current.name
Example:
<li ng-class="{active : $state.current.name === 'products'}">

Related

Get Id from url() in angular

How to get id from url()This is my url
http://localhost:59113/Project/EditProject?id=2
I did it using jquery..
var url = document.URL;
var id = /id=([^&]+)/.exec(url)[1];
var result = id ? id : ' ';
But I need to do it using angular.Can anyone help me?I tried this too(updated part)
var app = angular
.module("intranet_App", [])
app.config("$routeProvider", function ($routeProvider) {
$routeProvider.when('/view1/:param1/:param2', {
templateUrl: 'Project/EditProject.html',
controller: 'myCtrl'
})
})
.controller("myCtrl", ["$scope", "$http", "$location", "$route", function ($scope, $http, $location, $route) {
// alert($location.id)
var a = $route.current.params;
alert(a.id)
}])
Using $routeParams you can get id,
Updated answer
Use $route instead of $routeParams. Note that the $routeParams are only updated after a route change completes successfully. This means that you cannot rely on $routeParams being correct in route resolve functions. Instead you can use $route.current.params to access the new route's parameters.
$route.current.params
EDIT
You must do this in .config() method
app.config(function($routeProvider){
$routeProvider.when('/view1/:param1/:param2', {
templateUrl: 'Project/EditProject.html',
controller: 'myCtrl'
})
})
$location.search() returns an object, so as per above url
http://localhost:59113/Project/EditProject?id=2
$location.search().id will fetch you an answer.
More Info:
If you are getting an empty object with $location.search(), it is probably because Angular is using the hashbang strategy, To fix this you need to change the following in config file
$locationProvider.html5Mode(true);
$location.search() will return an object of key-value pairs.
in your case:You could access this value directly with $location.search().id

Get resolve variable and pass to controller

Hi I created a model named billerModel and a route that has a resolve with a variable of billers. Now I want to retrieve and assign this variable inside my controller but I get this billerData unknown provider error. Below are my code for the route:
app.config(["$routeProvider", "$httpProvider",'$locationProvider',function($routeProvider, $httpProvider, $locationProvider) {
$routeProvider
.when("/billers", {
templateUrl: 'admin/billers/index.html',
controller: 'billerController',
resolve: {
billerData: function(billerModel) {
return billerModel.getData();
}
}
});
Below is my code for the model
app.factory('billerModel', ['$http', '$cookies', function($http, $cookies) {
return {
getData: function() {
return $http({
method: 'GET',
url: 'billers'
});
}
}
}]);
Below is my controller code that gives me the error
app.controller('billerController', ['$scope', 'billerData',
function($scope, billerData){
$scope.billers = billerData;
}]);
I also tried to remove the ng-controller from my view but if I do this then I get an error of unknown variable
<div style="text-align: left;" ng-controller="billerController">
{{ billers }}
</div>
Below is a jsfiddle but I'm not familiar on how to use it but the basic structure is included here
https://jsfiddle.net/bd06cctd/1/
Resolve data in .when blocks is only injectable into controllers defined by the .when block. Child controllers injected by the ng-controller directive can not inject resolve data.
Also if you inject billerController in the .when block and with the ng-controller directive in the .when block template, then the controller will be instantiated twice.
The $routeProvider also makes resolve data available on the view scope on the $resolve property. Child controllers instantiated by the ng-controller directive can use that.
app.controller('childController', ['$scope',
function($scope){
$scope.billers = $scope.$resolve.billerData;
}]);
Controllers instantiated by the ng-controller directive will find the $resolve property by prototypical inheritance from the view scope.
From the Docs:
resolve - {Object.<string, Function>=} - An optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated. If all the promises are resolved successfully, the values of the resolved promises are injected and $routeChangeSuccess event is fired. If any of the promises are rejected the $routeChangeError event is fired. For easier access to the resolved dependencies from the template, the resolve map will be available on the scope of the route, under $resolve (by default) or a custom name specified by the resolveAs property.
-- AngularJS $routeProvider API Reference
Could you try changing:
app.factory('billerModel', ['$http', '$cookies', function($http, $cookies) {
return {
getData: function() {
return $http({
method: 'GET',
url: 'billers'
});
}
}
}]);
to
app.factory('billerModel', ['$http', '$cookies', function($http, $cookies) {
return {
getData: $http({
method: 'GET',
url: 'billers'
});
}
}]);
You're returning an anonymous function, not a Promise

Angular Ui-router can't access $stateParams inside my controller

I am very beginner in Angular.js, I am using the Ui-router framework for routing.
I can make it work upto where I have no parameters in the url. But now I am trying to build a detailed view of a product for which I need to pass the product id into the url.
I did it by reading the tutorials and followed all the methods. In the tutorial they used resolve to fetch the data and then load the controller but I just need to send in the parameters into the controllers directly and then fetch the data from there. My code looks like below. when I try to access the $stateParams inside the controller it is empty. I am not even sure about whether the controller is called or not.
The code looks like below.
(function(){
"use strict";
var app = angular.module("productManagement",
["common.services","ui.router"]);
app.config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider)
{
//default
$urlRouterProvider.otherwise("/");
$stateProvider
//home
.state("home",{
url:"/",
templateUrl:"app/welcome.html"
})
//products
.state("productList",{
url:"/products",
templateUrl:"app/products/productListView.html",
controller:"ProductController as vm"
})
//Edit product
.state('ProductEdit',{
url:"/products/edit/:productId",
templateUrl:"app/products/productEdit.html",
controller:"ProductEditController as vm"
})
//product details
.state('ProductDetails',{
url:"/products/:productId",
templateUrl:"app/products/productDetailView.html",
Controller:"ProductDetailController as vm"
})
}]
);
}());
this is how my app.js looks like. I am having trouble on the last state, ProdcutDetails.
here is my ProductDetailController.
(function(){
"use strict";
angular
.module("ProductManagement")
.controller("ProductDetailController",
["ProductResource",$stateParams,ProductDetailsController]);
function ProductDetailsController(ProductResource,$stateParams)
{
var productId = $stateParams.productId;
var ref = $this;
ProductResource.get({productId: productId},function(data)
{
console.log(data);
});
}
}());
NOTE : I found lot of people have the same issue here https://github.com/angular-ui/ui-router/issues/136, I can't understand the solutions posted their because I am in a very beginning stage. Any explanation would be very helpful.
I created working plunker here
There is state configuration
$urlRouterProvider.otherwise('/home');
// States
$stateProvider
//home
.state("home",{
url:"/",
templateUrl:"app/welcome.html"
})
//products
.state("productList",{
url:"/products",
templateUrl:"app/products/productListView.html",
controller:"ProductController as vm"
})
//Edit product
.state('ProductEdit',{
url:"/products/edit/:productId",
templateUrl:"app/products/productEdit.html",
controller:"ProductEditController as vm"
})
//product details
.state('ProductDetails',{
url:"/products/:productId",
templateUrl:"app/products/productDetailView.html",
controller:"ProductDetailController as vm"
})
There is a definition of above used features
.factory('ProductResource', function() {return {} ;})
.controller('ProductController', ['$scope', function($scope){
$scope.Title = "Hello from list";
}])
.controller('ProductEditController', ['$scope', function($scope){
$scope.Title = "Hello from edit";
}])
.run(['$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}])
.controller('ProductDetailController', ProductDetailsController)
function ProductDetailsController ($scope, ProductResource, $stateParams)
{
$scope.Title = "Hello from detail";
var productId = $stateParams.productId;
//var ref = $this;
console.log(productId);
//ProductResource.get({productId: productId},function(data) { });
return this;
}
ProductDetailsController.$inject = ['$scope', 'ProductResource', '$stateParams'];
Check it here
But do you know what is the real issue? Just one line in fact, was the trouble maker. Check the original state def:
.state('ProductDetails',{
...
Controller:"ProductDetailController as vm"
})
And in fact, the only important change was
.state('ProductDetails',{
...
controller:"ProductDetailController as vm"
})
I.e. controller instead of Controller (capital C at the begining)
The params in controller definition array should be strings
["ProductResource", "$stateParams"...
This should properly help IoC to inject the $stateParams
And even better:
// the info for IoC
// the style which you will use with TypeScript === angular 2.0
ProductDetailsController.$inject = ["ProductResource", "$stateParams"];
// this will just map controller to its name, parmas are defined above
.controller("ProductDetailController", ProductDetailsController);

Can't access value of scope in AngularJS. Console log returns undefined

I'm using ui-router for my application and nesting controllers within ui-view. My parent controller looks like this:
'use strict';
angular.module("discussoramaApp").controller("mainController", ["RestFullResponse", "Restangular", "localStorageService", "$scope", function(RestFullResponse, Restangular, localStorageService, $scope){
var currentId = localStorageService.get("***");
var user = Restangular.one("users", currentId);
var Profile = user.get({}, {"Authorization" : localStorageService.get('***')}).then(function(profile) {
$scope.profile = profile;
});
}]);
And my child controller:
'use strict';
angular.module("discussoramaApp").controller("getTopicsController", ["RestFullResponse", "Restangular", "localStorageService", "$scope", function(RestFullResponse, Restangular, localStorageService, $scope){
var topics = Restangular.all('topics');
var allTopics = topics.getList({},{"Authorization" : localStorageService.get('***')}).then(function(topics){
$scope.topics = topics;
});
console.log($scope); // this works
console.log($scope.profile); // this returns undefined
}]);
The problem I'm having is getting the inherited $scope value for profile in the child controller. When I log $scope, profile is clearly visible in the console.
But when I try to log $scope.profile the console returns undefined. Any ideas?
Edit: Adding my ui-router config.
angular.module("discussoramaApp").config(
function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise('/home');
$urlRouterProvider.when('', '/home');
$stateProvider
.state('main',{
url: '',
templateUrl: 'partials/main.html',
requireLogin: true
})
.state('main.home',{
url: '/home',
templateUrl: 'partials/main.home.html',
requireLogin: true,
title: 'Home'
});
}
);
And the corresponding html files:
// main.html
<div ng-controller="mainController">
<div class="container">
<div ui-view></div>
</div>
</div>
and the child html partial:
// main.home.html
<div ng-controller="getTopicsController">
<div ng-repeat="topic in topics | filter:search">
<a ui-sref="main.topic({id: topic.id})">{{ topic.topic_title }}</a>
</div>
</div>
UPDATE: Solved this with a watcher set up like this in the child controller. Thanks #jonathanpglick and #Nix for the help.
$scope.$watch('profile', function(profile) {
if(profile) {
$window.document.title = "Discussorama | " + profile.user.name;
}
});
$scope.profile is being set after an asynchronous request so I suspect that the second controller is being instantiated before user.get() returns and assigns a value to $scope.profile.
I think you'll want to set up a watcher (like $scope.$watch('profile', function(profile) {});) in the child controller so you can do things when the profile becomes available or changes.
Also, the reason you can see the profile key on $scope when you console log $scope can be explained here: https://stackoverflow.com/a/7389177/325018. You'll want to use console.dir() to get the current state of the object when it's called.
UPDATE:
I just realized you're using the ui-router and so there's an even easier way to do this. The ui-router has a resolve object that you can use to dependency inject things like this into your controller. Each resolve function just needs to return a value or a promise and it will be available for injection into the controller with resolve key name. It would look like this for you:
angular.module("discussoramaApp").config(
function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise('/home');
$urlRouterProvider.when('', '/home');
$stateProvider
.state('main',{
url: '',
templateUrl: 'partials/main.html',
requireLogin: true,
resolve: {
profile: ['Restangular', 'localStorageService', function(Restangular , localStorageService) {
var currentId = localStorageService.get("***");
var user = Restangular.one("users", currentId);
return user.get({}, {"Authorization" : localStorageService.get('***')});
}
}
})
.state('main.home',{
url: '/home',
templateUrl: 'partials/main.home.html',
requireLogin: true,
title: 'Home'
});
}
);
angular.module("discussoramaApp").controller("mainController", ["profile", "$scope", function(profile, $scope){
$scope.profile = profile;
}]);
Just because you have nested scope, doesn't mean it will wait for user.get() to return before instantiating your nested getTopicsController.
Your issue is:
mainController controller initializes and calls user.get()
getTopicsController initializes and logs console.log($scope.profile)
The call to user.get() returns and then sets on scope.
This is a common issue, if you need to gaurantee that $scope.profile is set, use resolve or watch the variable.
I actually gave an example of how to do this earlier today: AngularJS $rootScope.$broadcast not working in app.run

AngularJS - How to Use Service in Template

I can access a service such as $routeParams from the controller like so.
angular.module('myModule', []).
controller('myCtrl', ['$routeParams',
'$scope', function($routeParams,
$scope) {
console.log($routeParams['my-route-param']);
}])
But how would I do the same from a template. I tried the following code to no avail.
<h1 ng-hide="$routeParams['my-route-param']">No route param!</h1>
I know you could always save the value to $scope, but I am looking for a cleaner solution.
You can assign routeParams to a property of $scope:
controller('myCtrl', ['$routeParams',
'$scope', function($routeParams,
$scope) {
...
$scope.$routeParams = $routeParams
...
}
and then this would work:
<h1 ng-hide="$routeParams['my-route-param']">No route param!</h1>
Reason for that is every property you are accessing from template should be defined in current scope, which of course is not the case for parameter of controller constructor.
NB: in case of controller as syntax used you would do the same with controller, not scope:
controller('myCtrl', ['$routeParams',
'$scope', function($routeParams,
$scope) {
...
this.$routeParams = $routeParams
...
}
and markup:
<div ng-controller="myCtrl as ctrl">
<h1 ng-hide="ctrl.$routeParams['my-route-param']">No route param!</h1>
It's a bit late, but I had enough of copying $routeParams into my $scope only to be able to use them in my views, so I created a directive to do so.
Let's say you have this routing config:
...
angular.module( 'myApp' ).config( [ '$routeProvider', function( $routeProvider ) {
$routeProvider.when( '/view1/:param1/:param2', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
});
}])
...
And in your view1.html:
<h1 isteven-rr>$routeParams says: [[param1]] [[param2]]</h1>
If you have this in your URL bar: http://localhost/#/view1/Hello/World!
Then you'll see:
$routeParams says: Hello World!
Fork & learn more: https://github.com/isteven/angular-route-rage
Hope it can help shorten development time! Cheers!

Resources