I have 2 controllers, I want to have next thing:
when I click on item in controllerOne it should highlight element with the same ID in controllerTwo.
I have highlighting method But how to send event with ID from controllerOne to controllerTwo ??
Keep the shared data in a service that's accessible from both controllers, see https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#defer-controller-logic-to-services
Use $route to pass variables in the URL:
/controller2route/:action/:id
for example:
/details/highlight/2
You can then use ifs and switches to call the appropriate function, for example highlight(2) for the above URL.
https://docs.angularjs.org/api/ngRoute/service/$route
You can you route parameter in routing.
In routing
app.config(function($routeProvider) {
$routeProvider
.when("/users/:userId", {
templateUrl : "main.htm",
controller:"controllerTwo "
})
})
and in controllerTwo use $routeParams to get the user id.
app.controller('controllerTwo',function($scope,$routeParams){
var userId = $routeParams.userId;
})
and the one better solution is to use services. Here is the link
https://thinkster.io/a-better-way-to-learn-angularjs/services
Related
Basically, this is a social sort of application that I am working on.
So, for this app to work, the '/home' state shows a list of users. The 'friends/X' (X being user id) shows the profile of that user.
So, here is my app with the ng controller in the element:
ng-click="profile({{friend.id}})"
This hooks up and sends a function call to my controller "HomeController" which is currently in "/home". My problem is, how do I open a new state and pass a variable, the friend.id in this case to the state?
Thank you :)
EDIT:
Basically I want to know how a function "profile" can capture the id, then call the new state and send it the variable id of friend.id
EDIT 2:
Basically, in the profile function which is in the "HomeController" it will accept a ID as a perameter, so for example "1", and it will use the value it received and send the application to a NEW state for example now the new state is going to be "ProfileController" and it will be "/home/profile" or something like that, and it will pass along the "1" into the url, like so: "/home/profile/1".
If you want to do this inside a function, you should use the $location service to change the URL. Then the route will update, and the profile controller can take over.
<a ng-click="profile(friend.id)">{{friend.name}}</a>
... And in the controller:
$scope.profile = function(id) {
$location.url('/home/profile/' + id);
};
However, unless you need to do something with the click before changing the route, you can probably just do it with an href:
<a ng-href="#/home/profile/{{friend.id}}">{{friend.name}}</a>
If you stick to this method and leave it to the routing mechanism to choose the right controller, then your user will be able to copy/bookmark/jump to that URL directly, and use the back/forward buttons in the browser.
Use the $routeProvider service to tell AngularJS which controller to use based on the URL. For example (this should go in your module's .config):
$routeProvider
.when('/home/profile/:friendId', {
templateUrl: 'profile.html',
controller: 'ProfileController'
})
...etc
Then you can use $routeParams in ProfileController to get the current friendId parameter.
I use ui-router to be the route,but when I use $state.go(),I can redirect but cannot get the params I've passed,like this
.....
$state.go('detail',{people_id : people_id});
In official APIs,it says that I can pass a map as parameter which will populate $stateParams,but it doesn't work in my app
angular.module('xx').controller('aaaa',['$scope','$stateParams', function($scope, $stateParams){
console.log($stateParams); //empty obj
}])
So what the problem probably is? Thanks
In configuration you need to define url property to accept parameter
$stateProvider.state('detail', {
url: 'people/detail/:id'
...
});
I have a couple of states the use the same controller. Some of these do not require a URL parameter while some do. How do I avoid a state from being accessible if the URL parameter is not provided?
Example:
I have 2 views or states, list and single. They both share the same controller. I have the routes mapped as follows:
state: app.list
url: /list
controller: appCtrl
state: app.single
url: /single/:id
controller: appCtrl
Now, I want single to be accessed only if the id is specified, other wise redirect to some other page. How is that possible using the same controller?
Approach 1
You can use $urlRouterProvider with when() for redirection.
app.config(function($urlRouterProvider){
// when there is an single route without param, redirect to /list
$urlRouterProvider.when('/single/:id', ['$match', '$state', function($match, $state) {
if($match.id === ""){
$state.transitionTo("app.list");
}
}
]);
});
Working demo: http://plnkr.co/edit/sEoUGGCEge0XbKp3nQnc?p=preview
Approach 2
You can check the param in controller side and redirect it to specific page
myApp.controller('MainCtrl', function($state, $stateParams) {
if($state.current.name == 'app.single' && $stateParams.id === ""){
$state.transitionTo("app.list");
}
});
Working demo: http://plnkr.co/edit/QNF1RHy4Prde4CRhNLFa?p=preview
Note: In the above demos, redirection works when your current state should not be app.single. Means, State will not change if you are in app.single state and trying without param. So go to main page, then click the link without param of single state. it will redirect to list state.
I've seen this and this but it seems like there might be a simpler way.
In my view I have several menu options that are controlled through permissioning - i.e., not everyone can see a "Dashboard" view. So in my menu option in my view I have something like the following:
<li ng-show="validatePermission('Dashboard')">Dashboard</li>
In my controller I have a validatePermission method defined where it is looking at the permissions of the current user. For example:
$scope.validatePermission = function(objectName) {
if $scope.allPermissions......
Also in my controller I'm loading those permissions via an $http call:
$http.get('permissions/' + userid + '.json').success(function(data) {
$scope.allPermissions = data;....
The issue is that $scope.allPermissions doesn't get loaded before the view makes the call to validatePermission. How can I wait for allPermissions to be loaded before the view renders?
You ask:
How can I wait for allPermissions to be loaded before the view renders?
To prevent the entire view from rendering, you must use resolve. You don't have to use the promise library though, since $http returns a promise:
var app = angular.module('app');
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl : 'template.html',
controller : 'MyCtrl',
resolve : MyCtrl.resolve
});
});
function MyCtrl ($scope, myHttpResponse) {
// controller logic
}
MyCtrl.resolve = {
myHttpResponse : function($http) {
return $http({
method: 'GET',
url: 'http://example.com'
})
.success(function(data, status) {
// Probably no need to do anything here.
})
.error(function(data, status){
// Maybe add an error message to a service here.
// In this case your $http promise was rejected automatically and the view won't render.
});
}
}
But if you simply want to hide the dashboard <li>, then do as Joe Gauterin suggested. Here's a very simple example plunkr if you need it.
Have the validatedPermission function return false when allPermissions hasn't been loaded. That way the element with your ng-show won't be displayed until allPermissions has been loaded.
Alternatively, put an ng-show="allPermissions" on the enclosing <ul> or <ol>.
You can also specify on your routecontroller a resolve object that will wait for that object to resolve prior to rendering that route.
From the angular docs: https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
resolve - {Object.=} - An optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, they will be resolved and converted to a value before the controller is instantiated and the $routeChangeSuccess event is fired. The map object is:
key – {string}: a name of a dependency to be injected into the controller.
factory - {string|function}: If string then it is an alias for a service. Otherwise if function, then it is injected and the return value is treated as the dependency. If the result is a promise, it is resolved before its value is injected into the controller.
A google group reference as well: https://groups.google.com/forum/#!topic/angular/QtO8QoxSjYw
I encountered an similar situation, you might also want to take a quick look at
http://docs.angularjs.org/api/ng/directive/ngCloak
if you're still seeing a "flicker" effect.
As per the angularjs documentation:
The ngCloak directive is used to prevent the Angular html template from being briefly displayed by the browser in its raw (uncompiled) form while your application is loading. Use this directive to avoid the undesirable flicker effect caused by the html template display.
Wrapping the code in ng-if fixed the issue for me:
<div ng-if="dependentObject">
<!-- code for dependentObject goes here -->
</div>
I'm using the following to do paging in my datagrid:
$location.search('page', page);
where page is the current page number.
Then I listen to the following event:
$scope.$on('$routeUpdate', function(next, current) {
$scope.currentPage = $routeParams.page ? Number($routeParams.page) : 1;
$scope.search();
});
That triggers a call to a search() method on my scope after updating the currentPage that is in the URL.
How would I translate that to states with ui-router ? The $routeUpdate is no longer triggered since I'm using a state manager instead of routes.
My route is now defined in the state provider as such:
$stateProvider
.state('mandats', {
url: '/domiciliations/mandats',
templateUrl: 'domiciliations/views/mandats.html',
controller: 'mandatsCtrl'
})
I ended up listening to the $locationChangeSuccess event instead and that solved it.
I would try to use the controller (mandatsCtrl in your example) to put that logic. the view controller will be called with every parameter change, and you could inject the $stateParams into it to get the page #
other similar option to explore is the view controllers which is what I've used at some point
last, since $stateParams is injectable, you might want to inject it to your custom-built directive and use it there straight