Angular Links in view not working - angularjs

I am just beginning to experiment with AngularJS and have come across a problem.
My main page renders a <ng-view> element and I have set up the following routes:
(function () {
var routes = function ($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'Home/Overview',
controller: 'OverviewPageController'
})
.when('/Issue/:id', {
templateUrl: 'Home/Issue'
})
.otherwise({ redirectTo: '/' });
}
routes.$inject = ['$routeProvider'];
angular.module('PublicationSchedulerApp')
.config(routes);
}());
If I add a link tag outside of the <ng-view>:
<a ng-href="#/Issue/123">Issue</a>
The 'Issue' page is loaded into the view as expected.
In my case however, the Overview controller loads some data via an asynchronous Ajax call and then renders a table with a custom directive which, in turn, uses <ng-repeat>. If I create the same link within this directive/table:
<tr ng-repeat="issue in issues">
<td>
<a ng-href="#/issue/{{ issue.issueId }}">{{ issue.subject }}</a>
</td>
</tr>
The routing doesn't work. As you can see, I have played around with changing the link attribute from href to ng-href but this doesn't seem to make any difference. I am guessing that the asynchronous loading of the data is somehow breaking the routing, but I am not sure how to fix it. A couple of posts suggested that I reload the $route after the data load:
angular.module('PublicationSchedulerApp')
.run(['$route', function ($route) {
$route.reload();
}]);
but this didn't appear to make any difference either.
Any help would be much appreciated - thanks.

In Angular, routes are case sensitive. So make sure that your links match your route.
<tr ng-repeat="issue in issues">
<td>
<a ng-href="#/Issue/{{ issue.issueId }}">{{ issue.subject }}</a>
</td>
</tr>
You can also use ui-router, that way you will be able to create your links with state names rather than URLs (easier to maintain and less error-prone).

Related

Angularjs, Redirect views from controller

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

More efficient method of passing $routeParams in the same view

I have a button that's passing $routeParams
However this is too slow/clunky as it reloads the entire view by going to the same URL collections.html
Angular
$routeProvider.when('/products/:uId/:mId/productsList', {
templateUrl: '/views/collections.html',
controller: 'productsController'
});
HTML
<tr> ng-repeat="(key, product) in products">
<td>{{product.name}}</td>
<td>{{product.value}}</td></tr>
Is their a method of passing the $routeParams and loading a partial view
without reloading the entire view to speed things up a bit ?
e.g. ng-include instead of ng-href

How to prevent losing data when moving from one state to another in multi-step form?

I am new to web programming and especially to AngularJS.
So maybe my question will seem naive to some of you.
I'm developing a single page application using angular-ui-router.
I have created a multi-step form that contains 3 states:
(function () {
"use strict";
angular.module("sensorManagement", ["ui.router", "ngAnimate", "ngResource", "toaster"])
.config(["$stateProvider", "$urlRouterProvider", function ($stateProvider, $urlRouterPorvider) {
$urlRouterPorvider.otherwise("/Sensor/Home");
$stateProvider
.state("MultiStepForm", {
url: "/Sensor/MuiltyStepForm",
templateUrl: "/app/MultiStepForm/MuiltyStepForm.html",
})
.state('MultiStepForm.step1', {
url: '/step1',
templateUrl: '/app/MultiStepForm/FormStep1.html'
})
.state('MultiStepForm.step2', {
url: '/step2',
templateUrl: '/app/MultiStepForm/FormStep2.html'
})
.state('MultiStepForm.step3', {
url: '/step3',
templateUrl: '/app/MultiStepForm/FormStep3.html'
});
}]);
})();
Here is the HTML code:
<!-- form.html -->
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<div id="form-multiple-step">
<div class="page-header text-center">
<!-- the links to our nested states using relative paths -->
<!-- add the active class if the state matches our ui-sref -->
<div id="status-buttons" class="text-center">
<a ui-sref-active="active" ui-sref=".step1"><span>STEP1</span></a>
<a ui-sref-active="active" ui-sref=".step2"><span>STEP2</span></a>
<a ui-sref-active="active" ui-sref=".step3"><span>STEP3</span></a>
</div>
</div>
<form id="single-form">
<!-- our nested state views will be injected here -->
<div id="form-views" ui-view></div>
</form>
</div>
</div>
</div>
As you can see I have 3 states and each state has it's own view. The views have multiple elements (textboxes and checkboxes).
When the user enters some data for the STEP1 view and moves to the next step (STEP2 or STEP3) then at some point goes back to STEP1 all data is deleted. I checked with fiddler and can see that when I move from one state to another a call is made to the server and a new view generated.
My question is how can I prevent the lose of data when I move from one state to another? Do I have to use caching? Or maybe there is another way to prevent server calls and keep the data alive until the submit button clicked.
When you feel you have to save data across your controllers in your app. you should use a service.
app.factory('sharedDataService', function ($rootScope) {
console.log('sharedDataService service loaded.');
// do something here that can be shared in other controller
});
//pass this service in your controller to use it there
app.controller('Controller2', ['$scope', 'sharedDataService', function ($scope, sharedData) {
console.log('Controller2 controller loaded.');
//get data from shared service
}]);
find a useful Fiddle here
Cheers if it helps!
I think what you need to do is share you $scope between the parent and child stats. here is the stackoverflow post with good example. https://stackoverflow.com/a/27699798/284225

Unable to display angularjs page data after route change.

I am relatively new to angularjs and seems like I am missing something obvious here. I tried to go through documentation and tutorials, but unable to find any solution to my problem.
I have a REST service at "localhost:8080/app/rest/schools/{schoolId}/selectedindicators". I can display the results in an angularjs app page (selectedindicator.html) like so:
<tbody>
<tr ng-repeat="selectedindicator in selectedindicators">
<td>{{selectedindicator.id}}</td>
<td>{{selectedindicator.school.name}}</td>
<td>{{selectedindicator.userId}}</td>
<td>{{selectedindicator.dateVisit}}</td>
<td>
<button type="submit"
ng-click="update(selectedindicator.id)"
class="btn">
<span class="glyphicon glyphicon-pencil"></span> Edit
</button>
</td>
</tr>
</tbody>
Until this point everything is working fine. But, when I try to select one of the selected indicators by clicking on the Edit button I can not display the data on the Edit (selectedindicatorForm.html) page. Here is chunk of my Edit page.
<div>
<div class="form-group">
<label>ID</label> <input type="text" class="form-control" name="id"
ng-model="selectedindicator.id" required>
</div>
.
.
.
.
.
.
</div>
Here is my routeProvider code:
myApp
.config(['$routeProvider', '$httpProvider', '$translateProvider',
function ($routeProvider, $httpProvider, $translateProvider) {
$routeProvider
.when('/selectedindicator', {
templateUrl: 'views/selectedindicators.html',
controller: 'SelectedIndicatorController',
resolve:{
resolvedSelectedIndicator: ['SelectedIndicator', function (SelectedIndicator) {
return SelectedIndicator.query();
}]
}
})
.when('/selectedindicatorForm',{
templateUrl: 'views/selectedindicatorForm.html',
controller: 'SelectedIndicatorFormController',
})
}]);
Here is my controller code for the update method:
myApp.controller('SelectedIndicatorController', ['$scope', '$location', '$route','resolvedSelectedIndicator', 'SelectedIndicator',
function ($scope, $location,$route, resolvedSelectedIndicator, SelectedIndicator) {
$scope.selectedindicators = resolvedSelectedIndicator;
$scope.update = function (id) {
$scope.selectedindicator = SelectedIndicator.get({id: id});
$location.path("/selectedindicatorForm");
};
}]);
you can add a separate service (singleton object) to pass data between controllers .
looks like you SelectedIndicator (which is passed onto SelectedIndicatorController) is already doing that and you can simply re-use it .
On your SelectedIndicatorFormController inject this service SelectedIndicator and call SelectedIndicator.get({id: id});
Note - looks like this line $scope.selectedindicator = SelectedIndicator.get({id: id}); inside SelectedIndicatorController doesn't serve any purpose.
If you could setup a plunk, I could help you.
Is there some reason you're transitioning using $location.path?
The way I'd do that would be just put an or something, with a class="btn" or some other css styling if you really want it to look like a button. With regular ngRoute, you just work with URLs, and should put all the state into the URL. I'm pretty sure setting a $scope variable and then manually changing the state doesn't actually do anything, since the new state has its own $scope.
To be perfectly frank after looking at that code, I'm going to say that you probably ought to read some angular tutorial stuff. I found egghead.io to be pretty great myself.

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

Resources