Angularjs, Redirect views from controller - angularjs

I'm new to angularJS. I'm using angularjs to implement a website. The website has two pages. The first page list all items and if user click on it, it will redirect to detail information page.
I have my routes configure as below:
var app = angular.module('myApp', ["ngRoute"]);
app.config(function($routeProvider) {
$routeProvider
.when("/list", {
templateUrl : "list.html",
controller : "listCtrl"
})
.when("/detail/:id"){
templateUrl : "detail.html"
}
});
In the list.html. I use ng-repeat to display a list of items and a listener on to listen mouse click.
<ul class="list-group">
<li class="list-group-item" ng-repeat="i in items">{{i.name}}
<a href="#" ng-click="goToEdit($index)">
<span class="glyphicon glyphicon-pencil"></span>
</a>
</li>
</ul>
I want to redirect view to detail information in the ng-click function.
I tried $location.path() but it not working.
$scope.goToEdit = function(index){
console.log($location.path());
$location.path("/detail/" + index);
console.log($location.path());
}
This way won't work.
Even though the second log on console show location.path() has been changed to " /detail/id".
If I add $scope.$apply() after $location.path(); Then I will get a action already in progress error.
Do you have any solution???
Thanks

It might have something to do with use href="#" which is not good when using hash based routing
You could just set the href yourself and don't really need the controller function or ng-click
<a ng-href="#/detail/{{$index}}" >
Note that you should really give each item a unique identifier as $index could change due to using filters in ng-repeat or removing data from array
Also you don't have a controller identified for your second route

Related

AngularJs scrollTo issue

I am making a menu with AngularJs and I want that, clicking on the item, the page will scroll to the section of the clicked item.
My code is the following:
script.js
var app = angular.module('allApps',['ui.bootstrap']);
app.controller("menuCtrl",function($scope, $location, $anchorScroll){
$scope.menuItems=[
{page:"Biography", id:"bio"},
{page:"Curriculum Vitae", id:"cv"},
{page:"Gallery", id:"gallery"},
{page:"Video", id:"video"},
{page:"Press", id:"press"},
{page:"News", id:"news"},
{page:"Contact", id:"contact"}
];
$scope.scrollTo = function(id) {
$location.hash(id);
console.log($location.hash());
$anchorScroll();
};
});
menu.html
<ul class="nav nav-pills" id="mainMenu" ng-controller="menuCtrl">
<li class="active">Home</li>
<li ng-repeat="item in menuItems"><a ng-click="scrollTo('{{item.id}}')" href="">{{item.page}}</a>
</ul>
the code like this doesn't work but, if I write explicitly
ng-click="scrollTo('bio')"
it does (obviously it will scroll all the links to biography page).
I thought it was a problem in reading AngularJs directions but if I check it with firebug I can see it takes the correct id's.
May you tell me what is wrong?
You had incorrect expression in ng-click directive, basically it should not contain {{}} interpolation directive in it. The expression which you provide to ng-click will directly evaluate with the context of controller
ng-click="scrollTo(item.id)"

Dynamic view names based on the parameters returned while calling the state

I am using Kendo tabstrip with angular ng-repeat and ui-router. Now the tabstrip can have different combination and different number of tabs based on the input. I am able to give different ui-sref and ui-view names to each tab while adding tabs dynamically using angular ng-repeat.
<div class="demo-section k-content">
<div kendo-tab-strip="detailsTabStrip" k-ng-delay="Tabs">
<ul>
<li ng-repeat="tab in Tabs" ng-class="getClass($first,tab)" ui-sref="{{tab.sref}}">
{{tab.name}}
</li>
</ul>
<div ng-repeat="tab in Tabs" ui-view="{{tab.view}}"></div>
</div>
</div>
So, this code gives an individual ui-view to each tab. There can 150 different types of views possible in tabs. So, I cannot hard code the view names in the router file. I need the router to accept a parameter for view name or at least in some way I can let the router know which view to populate with the html.
$stateProvider
.state('details.tab', {
url:'/tab/:tabName',
views:{
// the view name should be able to either read the state param and
// accordingly assign template or should at least be able to read the state
// and accordingly assign the template or if views can be a function.
"details.tabName": {
templateUrl: 'resources/pages/grid.html',
controller: 'gridController'
}
}
});
Is it possible to make the views names dynamic in any way. There are other parts in the application which have absolute ui-view defined and work perfectly. The changes made to make views names dynamic for this part should not affect the other parts of application. Can I use relative views to achieve this in any way? Thanks for all the help.
Also, if I am adding tabs to kendo-tab-strip dynamically using ng-repeat, can i specify a single ui-view="details" for the tabstrip. Like for all the tab states, populate details view.
<div kendo-tab-strip="tabStrip">
<ul>
<li ng-repeat="tab in Tabs" ng-class="getClass($first,tab)" ui-sref="{{tab.sref}}">
{{tab.name}}
</li>
</ul>
<div ui-view="details"></div>
</div>
If I do this, all the tab loads up fine first time but if I try to deep dive into tabs, for ex: if I try to deep dive into fifth tab, then the content for fifth tab loads up fine but its not shown. Even though the tab is shown as active(I am using ng-class as a function to decide which tab should be shown active by sending k-state-active to the appropriate tab while adding it).
And if I define different views for different tabs dynamically like below,
<div kendo-tab-strip="detailsTabStrip" k-ng-delay="Tabs">
<ul>
<li ng-repeat="tab in Tabs" ng-class="getClass($first,tab)" ui-sref="{{tab.sref}}">
{{tab.name}}
</li>
</ul>
<div ng-repeat="tab in Tabs" ui-view="{{tab.view}}"></div>
</div>
then dont know, how to tell state router which view should be populated when a particular tab is clicked. Like when third tab is clicked, the corresponding ui-view specified is ui-view="third",when fourth tab is clicked, the corresponding ui-view specified is ui-view="fourth" and so on.How to configure the views dynamically in ui-router?
Thanks a lot for all the help.
Make a common view, use that view name on your state provider.
In that view include your desiered view as
<ng-include ng-src="'resources/pages' + tabname + '.html'" />
A cleaner solution is provided here:
app.js:
app.config(function ($locationProvider, $urlRouterProvider, $stateProvider) {
$urlRouterProviderRef = $urlRouterProvider;
$locationProvider.html5Mode(false);
$stateProviderRef = $stateProvider;
});
app.run(['$q', '$rootScope', '$state', '$http',
function ($q, $rootScope, $state, $http)
{
$http.get("myJson.json")
.success(function(data)
{
angular.forEach(data, function (value, key)
{
var state = {
"url": value.url,
"parent" : value.parent,
"abstract": value.abstract,
"views": {}
};
angular.forEach(value.views, function (view)
{
state.views[view.name] = {
templateUrl : view.templateUrl,
};
});
$stateProviderRef.state(value.name, state);
});
$state.go("home");
});
}]);
Reference from AngularJS - UI-router - How to configure dynamic views

AngularJS UI Router - Nested state with individual views

I have a menu on my website, where the items have an active state. The default state is areas, then I can navigate through my website changing states.
<li ui-sref-active="active">
<a ui-sref="areas">
<span>Areas</span>
</a>
</li>
.state('areas', {
url: '/areas',
templateUrl : 'templates/areas.html',
controller : 'AreaCtrl'
})
In my areas.html template, I have a list, with items which can be clicked...:
<li ng-repeat="area in areas" ui-sref="areas.city({areaId: area.area_id, areaName: area.name})">
Now when one of these is clicked, I need to keep the active state on my menu. So the only way of doing this is via nested states...
.state('areas.city', {
url: "/:areaId/:areaName",
templateUrl: 'dist/templates/cities.html',
controller: 'CityCtrl'
})
However the problem is, my cities.html needs to be a totally new view (in place of where areas.html is), which isn't nested within areas (so I don't have a <ui-view> within areas.html).
I can, just not nest the view, so the state is .state('city', but then I lose the active state on the menu.
Any clue how I get around this?
You can activate the state in the main menu as like below
<li ng-class="{active: $state.includes('area') || $state.includes('areas.city')}">
<a ui-sref="areas">
<span>Areas</span>
</a>
</li>
Also, please apply the $state into $rootScope. So that you can access $state in any views.
myApp.run(function($rootScope, $state) {
$rootScope.$state = $state;
});

Problems with ng-router and anchor tab

MyApp.config([ '$routeProvider', function($routeProvider) {
$routeProvider
.when('/getAttributes', {
templateUrl : 'view/attributes.jsp',
controller : 'attributeController'
}).when('/mainMenu', {
templateUrl : 'view/mainmenu.jsp',
controller : 'mainMenuController'
}).otherwise({
redirectTo : '/mainMenu'
});
} ]);
We use the above routing configuration for implementing templates with Angular JS.
This gets called we we click on any anchor tag with some ID, its okay for dynamic pages but even for static links it tries to find the mapping.
For example in the below code we dont want the routing to be triggered. But it triggers and goes to the mainMenu. I tried location.path() in the controller but even then its the same, because we have defined the routerprovider it always redirects to mainmenu . Please suggest on how can control the trigger or is there any other way to implement this routing in AngularJS
<ul class="tabs promo-tabs" role="tablist" ng-repeat>
<li ><a target="_self" href="#staticTab1">tab1 </a></li>
<li ><a target="_self" href="#staticTab2">tab2</a></li>
</ul>
Updated it as per comment below still it didn't work after adding target="_self"
Add target="_self"
tab1

angular-ui-router dynamic menu: TypeError: Cannot call method 'match' of undefined while rendering menu

i am new to angular and angular-ui-router and trying to create a menu.
I tried angular-ui-router and think that it fits for my needs.
now i have a problem while creating the menu with the ui-router attributes.
my html code looks like that:
<div ng-controller="MenuCtrl">
<ul>
<li ng-repeat="item in menu">
<a ui-sref="cf.{{item}}">{{item}}</a>
</li>
</ul>
</div>
the menu array contains different entries dependent on the info if the user is logged in.
now i get this error message:
TypeError: Cannot call method 'match' of undefined
<a ui-sref="cf.{{item}}" class="ng-binding">
It looks like ui-router tries to get access to the list entry before it is rendered complete with ng-repeat.
What can i do to prevent this problem?
So ui-router doesn't support interpolation in ui-sref, believe me I wish they would. Here is how I solved this.
In your controller:
app.controller("MenuCtrl", ['$scope', '$state', function($scope, $state) {
$scope.$state = $state;
}]);
In your view use an ng-href to evaluate $state object that we've now added to the $scope:
<div ng-controller="MenuCtrl">
<ul>
<li ng-repeat="item in menu">
<a ng-href={{ $state.href('cf.' + item) }}>{{item}}</a>
</li>
</ul>
</div>
You can also you this technique for wildcard params:
ng-href="{{ $state.href('cf.items.item', {'item' : item} ) }}"
Assuming you've set up your ui-router routes properly for this.

Resources