Angular JS UI-Routing with stateparams not working after refresh - javascript

Using angular-ui-router with angular for routing in MEAN application
angular: 1.6.2,
angular-ui-router: 0.4.2
Having following state:
.state('myposts', {
url: '/your-posts',
controller:'PostListController',
templateUrl:'post-list.template.html'
})
.state('postdetail', {
url: '/post/:postId',
controller:'PostDetailController',
templateUrl:'postdetail.template.html',
resolve:{
postdetail: ['Post', '$stateParams', function (Post, $stateParams) {
var url = '/api/posts/edit/' + $stateParams.postId;
return Post.get(url);
}]
}
})
In post-list.template.html listed all posts in table and there is an link to edit particular post by using the following
<a ui-sref="postdetail({ postId: post._id })" class="btn btn-default">
It makes an transition from myposts to postdetail with postId parameter.
Actual URL http://localhost:8886/#/post/58d5167bf05b904a52158f58
Here postId is 58d5167bf05b904a52158f58
Resolve post with postId = 58d5167bf05b904a52158f58 in resolve property of ui-router and inject in PostDetailController controller
function PostDetailController($scope, $state, $stateParams, postdetail, Post){
$scope.post = postdetail;
....
}
It works normally first time, but not working when i refresh the page having url
http://localhost:8886/#/post/58d5167bf05b904a52158f58
Using express server ^4.13.4,
Anyone having solution of above problems, why it is happening
Thanks

Related

angular uirouter opens wrong url

I'm new to Angular 1 and have to implement a new feature on an existing webapp. The app uses jhipster to generate some parts of the backend and frontend (Angular 1 and uirouter).
So I tried to use my own route and state like this which is mostly copy and pasted from existing components of the webapp:
(function() {
'use strict';
angular
.module('artemisApp')
.config(stateConfig);
stateConfig.$inject = ['$stateProvider'];
function stateConfig($stateProvider) {
$stateProvider
.state('model-comparison-exercise-for-course', {
parent: 'entity',
url: '/course/{courseid}/model-comparison-exercise',
data: {
authorities: ['ROLE_ADMIN', 'ROLE_TA'],
pageTitle: 'artemisApp.modelComparisonExercise.home.title'
},
views: {
'content#': {
templateUrl: 'app/entities/model-comparison-exercise/model-comparison-exercise.html',
controller: 'ModelComparisonExerciseController',
controllerAs: 'vm'
}
},
resolve: {
translatePartialLoader: ['$translate', '$translatePartialLoader', function ($translate, $translatePartialLoader) {
$translatePartialLoader.addPart('modelComparisonExercise');
$translatePartialLoader.addPart('exercise');
$translatePartialLoader.addPart('global');
return $translate.refresh();
}],
courseEntity: ['$stateParams', 'Course', function ($stateParams, Course) {
return Course.get({id: $stateParams.courseid}).$promise;
}]
}
});
}
})();
Then I try to open this route with the following code:
<a ui-sref="model-comparison-exercise-for-course({courseid:course.id})"
data-translate="artemisApp.course.modelComparisonExercises"></a>
By clicking on that link a http get request is fired which returns a http status code 404: http://localhost:8080/app/entities/model-comparison-exercise/model-comparison-exercise.html
Actually, the url that should be opened is http://localhost:8080/#/course/1/model-comparison-exercise
Any idea what I could have configured wrong?
Please try changing 'content#' to 'content#artemisApp'.
As explained here:
The symbol before the # is the name of the view you want to match, and the symbol after the # is a reference to the state in which the template the ui-view directive should exist in.
And the <a> tag is not being closed:
<a ui-sref="model-comparison-exercise-for-course({courseid:course.id})"
data-translate="artemisApp.course.modelComparisonExercises"></a>
Searching through the code, I found that model-comparison-exercise.html does not exist in folder model-comparison-exercise. Besides model-comparison-exercises.html exist.

invoking an angular route from angular service to load a new view and controller

I'm trying to invoke a route through and angular service and since I am using $http.post I can't get the route to invoke. I may be going at this all wrong so I'm hoping someone can make a suggestion or point me in the right direction. Initally I have a page load with a controller which once the search command is called it passes a json object with the request to an angular service which then calls webAPI to pass the request onto my other business layers. Here is a logical diagram of the workflow. The response in blue is a new data object being returned to the UI with the users search results.
From my app I have the following routes setup
(function () {
app = angular.module('app', ['ui.bootstrap', 'ngRoute', 'ngAnimate']).value('ngToastr', toastr);
function router($routeProvider) {
$routeProvider.
when('/search/query', {
templateUrl: '../../AngularTemplates/searchResults.html',
controller: 'searchResultCtrl'
}).
otherwise({
templateUrl: '../../AngularTemplates/splashPage.html'
});
}
app.config(['$routeProvider', router]);
//added toaster as factory so it can be injected into any controller
angular.module('app').factory('ngNotifier', function (ngToastr) {
return {
notify: function (msg) {
ngToastr.success(msg);
},
notifyError: function (msg) {
ngToastr.error(msg);
},
notifyInfo: function (msg) {
ngToastr.info(msg);
}
}
});
})();
The initial page calls the controller which has a service dependency
app.controller('searchController', ['$scope', '$filter', 'searchService', 'ngNotifier', '$log', '$timeout', 'searchAttributes' , function ($scope, $filter, searchService, ngNotifier, $log, $timeout, searchAttributes) {
var vm = this;
vm.search = search;
vm.updateEntities = updateEntitySelection;
//bootstraped data from MVC
$scope.userOptions = searchAttributes.mvcData;
//scoped variables
$scope.searchTerm = null;
//ui container for search response
$scope.searchResponse;
$scope.entityList = [
'Search All ',
'Search in Departments ',
'Search in Automotive '
]
$scope.selectedEntity = 'Search All';
function buildSearchRequest() {
var searchResponse = {
searchTerm: $scope.searchTerm,
pageSize: 10,//this will be set by configuration from the UI
pagesReturned: 0,
entityFilter: $scope.selectedEntity
};
return searchResponse;
}
function onError(msg) {
$log.error('An error has occured: ' + msg.data);
}
function updateEntitySelection(entityName) {
$scope.selectedEntity = entityName;
}
function search() {
var request = buildSearchRequest();
searchService.search(request);
}
}]);
and the search service
app.factory('searchService', ['$http', function($http) {
var myEsResults;
function getSearchResults(searchRequest) {
return $http.post('search/query', searchRequest, {}).then(function (response) {
myEsResults = response.data});
}
var getResults = function () {
return myEsResults;
};
return{
search: getSearchResults,
getResults: getResults
};
}]);
What I am trying to accomplish is when the document loads a splash screen is displayed (which works). when the search is executed the request is passed to webapi and then the response is returned as an objectback to the view and a new controller so it can render the search results. I have passed data back and forth between controllers in the past however where I am stuck is using an angular service to call route in webapi. Making this call does not update the page URL and therefore the route is not invoked nor is the second controller loaded to display the results. In the past I have invoked angular routes using a url http://#/route however in this instance I am using an input button with ng-click. I would appreciate any suggestions as to how on the return of data get the 'result view' and controller to load. Is routing the correct approach or is there another way to load the view and controller when using an angular service?
Thanks in advance
<button type="button" class="btn btn-primary btn-lg" ng-click="vm.search()"><span class="glyphicon glyphicon-search"></span></button>
Should be able to do it using $location.path('/search/query')
function getSearchResults(searchRequest) {
return $http.post('search/query', searchRequest, {}).then(function (response) {
myEsResults = response.data;
$location.path('/search/query');
});
}
however workflow seems like it would make more sense to add either routeParams to the url or a search query param and pass url encoded query term to url and make request based on that. Then the request would be made by the searchResultCtrl controller or a resolve in the router config.
Something like:
$routeProvider.
when('/search/query/:queryterm', {
templateUrl: '../../AngularTemplates/searchResults.html',
controller: 'searchResultCtrl'
}).
And path would be generated by:
$location.path('/search/query/' + encodeURIComponent($scope.searchTerm) );

AngularFire - How to define item ID for child template with ng-repeat?

Maybe my issue seems easy to resolve, but I've this problem since a lot of hours : When I'm in my dashboard, all data of my Firebase database are visible (With Ng-repeat).
But I can't found a solution for choose one specific item and see his details in another page.
I've test this method in HTML (This is an example) :
<div ng-repeat="post in posts">
<div class="card" ng-href="#/post/">">
<h1>{{post.title}}</h1>
<p>{{post.content}}</p>
</div>
</div>
In App JS :
.state('tabpost', {
url: 'tabpost/id',
templateUrl: 'templates/tab-post.html',
controller: 'PostCtrl'
})
In Service JS (in Post Factory) :
myApp.factory("Post", ["$firebaseArray", "$firebaseObject", function($firebaseArray, $firebaseObject) {
var postRef = new Firebase('https://myApp.firebaseio.com/Posts/');
var userRef = new Firebase('https://myApp.firebaseio.com/Users/');
var posts = $firebaseArray(postRef);
var Post = {
all: posts,
get: function (postKey){
var postId = $firebaseObject(postRef);
return $firebaseObject(eventRef.child('Posts').child(postId).child(userid));
}
,
add: function (post){
var postId = $firebaseArray(postRef, userRef);
event.userid = userRef.getAuth();
return postId.$add(post);
}
}
return Post;
}]);
My PostCtrl :
myApp.controller('PostCtrl', ['$ionicFrostedDelegate', '$ionicScrollDelegate','$state','$scope', 'Post', 'Auth', '$firebaseObject', '$firebaseArray', function($ionicFrostedDelegate, $ionicScrollDelegate, $state,$scope, Post, Auth, $firebaseObject, $firebaseArray) {
var PostRef = new Firebase("https://myApp.firebaseio.com/Posts");
$scope.posts = Post.all;
$scope.post = {'title': '', 'content': ''};
$scope.auth = Auth;
PS : It took 16 hours to try a bunch of tutorials mostly obsolete , and I am sure that the solution can not be that simple.
I already posted two similar issues yesterday and this morning but each of the proposed solutions have not worked . I would be immensely grateful to the person who would help me out of this impasse .
I still have a little trouble with jsFiddle promised I would learn to use it once I would have solved this problem.
Thank you for giving me time
Can you please try the following set of codes, I've explained the changes in comments in Controller and added :id in App JS
In App JS :
.state('tabpost', {
url: 'tabpost/:id',
templateUrl: 'templates/tab-post.html',
controller: 'PostCtrl'
})
PostCtrl :
myApp.controller('PostCtrl', ['$ionicFrostedDelegate', '$ionicScrollDelegate','$state','$scope', 'Post', 'Auth', '$firebaseObject', '$firebaseArray', '$routeParams', function($ionicFrostedDelegate, $ionicScrollDelegate, $state,$scope, Post, Auth, $firebaseObject, $firebaseArray, $routeParams) {
var PostRef = new Firebase("https://myApp.firebaseio.com/Posts");
var id = $routeParams.id; //get the id from url, $routeParams is injected in controller
$scope.posts = Post.get(id); //call get() method of Post with the id retrieved
$scope.post = {'title': '', 'content': ''};
$scope.auth = Auth;
you can use route provider to do that. I used that for my application and it works great.
myApp.config( ['$routeProvider', function($routeProvider){
$routeProvider.
when('tabpost', {
templateUrl: 'tabpost/id',
controller: 'PostCtrl'
});
}]);

AngularFire - Error: Could not resolve '#/tabpost' from state 'tabdash' [duplicate]

This question already has answers here:
AngularFire - How to define item ID for child template with ng-repeat?
(2 answers)
Closed 7 years ago.
Maybe my issue seems easy to resolve, but I've this problem since a lot of hours : When I'm in my dashboard, all data of my Firebase database are visible (With Ng-repeat).
But I can't found a solution for choose one specific item and see his details in another page.
I've test this method above and I've this error "Error: Could not resolve '#/tabpost' from state 'tabdash".
This is the HTML (This is an example) :
<div ng-repeat="post in posts">
<div class="card" ui-sref="#/post/{id}">
<h1>{{post.title}}</h1>
<p>{{post.content}}</p>
</div>
</div>
In App JS :
.state('tabpost', {
url: 'tabpost/id',
templateUrl: 'templates/tab-post.html',
controller: 'PostCtrl'
})
In Service JS (in Post Factory) :
myApp.factory("Post", ["$firebaseArray", "$firebaseObject", function($firebaseArray, $firebaseObject) {
var postRef = new Firebase('https://myApp.firebaseio.com/Posts/');
var userRef = new Firebase('https://myApp.firebaseio.com/Users/');
var posts = $firebaseArray(postRef);
var Post = {
all: posts,
get: function (postKey){
var postId = $firebaseObject(postRef);
return $firebaseObject(eventRef.child('Posts').child(postId).child(userid));
}
,
add: function (post){
var postId = $firebaseArray(postRef, userRef);
event.userid = userRef.getAuth();
return postId.$add(post);
}
}
return Post;
}]);
My PostCtrl :
myApp.controller('PostCtrl', ['$ionicFrostedDelegate', '$ionicScrollDelegate','$state','$scope', 'Post', 'Auth', '$firebaseObject', '$firebaseArray', '$routeParams', function($ionicFrostedDelegate, $ionicScrollDelegate, $state,$scope, Post, Auth, $firebaseObject, $firebaseArray, $routeParams) {
var PostRef = new Firebase("https://myApp.firebaseio.com/Posts");
var id = $routeParams.id; //get the id from url, $routeParams is injected in controller
$state.go('tabpost', {
id: $scope.id
});
$scope.posts = Post.get(id); //call get() method of Post with the id retrieved
$scope.post = {'title': '', 'content': ''};
$scope.auth = Auth;
PS : It took 3 days and night to try a bunch of tutorials mostly obsolete , and I am sure that the solution can not be that simple.
I already posted three similar issues yesterday and later but each of the proposed solutions have not worked . I would be immensely grateful to the person who would help me out of this impasse .
I still have a little trouble with jsFiddle promised I would learn to use it once I would have solved this problem.
Thank you for giving me time
You need to prefix your variable names with a colon in your state's URL. Your ui-router state should be
.state('tabpost', {
url: 'tabpost/:id',
templateUrl: 'templates/tab-post.html',
controller: 'PostCtrl'
});
and you should link to it like
<div class="card" ui-sref="tabpost/{id}">

Angular-UI-Router: ui-sref not building href with parameters

I have an HTML page, once loaded in the user's browser the 'list' state is activated and the 'list' partial is pulled by Angular and populated with a list of servers.
Each server has a 'details' link that specifies the 'details' state for that server.
<td><a ui-sref="details({ serverName: '{{server.name}}' })">Details</a></td>
When rendered the 'ui-sref' generates the expected 'href' url based on the route and its optional parameters.
<a ui-sref="details({ serverName: 'SLCMedia' })" href="#/details/SLCMedia">Details</a>
When clicked it works as expected and the 'details' partial is pulled and in the controller assigned to that state pulls the server with the name specified.
The issue I am running into is the fact that once the 'details' partial is loaded, it too has a 'ui-sref' to an 'edit' state.
<a ui-sref="edit({ serverName: '{{server.name}}' })">
<button class="btn btn-lg btn-labeled btn-primary">
<span class="btn-label icon fa fa-edit"></span>
Edit
</button>
</a>
But when this partial is loaded the 'ui-sref' is not generating the correct 'href' url.
<a ui-sref="edit({ serverName: 'SLCMedia' })" href="#/edit/">
<button class="btn btn-lg btn-labeled btn-primary">
<span class="btn-label icon fa fa-edit"></span>
Edit
</button>
</a>
As you can see the 'href' url is '#/edit/' not '#/edit/SLCMedia' as would be expected. It's got to be something simple that I am missing. Does the change of state have something to do with it?
Here are all of defined 'states' for the page.
// Create the Angular App to rule the Server Management Page
var serverApp = angular.module('serverApp', [
'ui.router',
'serverControllers',
'utilitiesService'
]);
serverApp.config(function ($stateProvider, $urlRouterProvider) {
// For any unmatched url, redirect to /state1
$urlRouterProvider.otherwise("/list");
// Now set up the states
$stateProvider
.state('list', {
url: '/list',
templateUrl: '/views/pages/servers/list.html',
controller: 'serverListCtrl'
})
.state('details', {
url: '/details/:serverName',
templateUrl: '/views/pages/servers/details.html',
controller: 'serverDetailsCtrl'
})
.state('create', {
url: '/create',
templateUrl: '/views/pages/servers/create.html'
})
.state('edit', {
url: '/edit/:serverName',
templateUrl: '/views/pages/servers/edit.html',
controller: 'serverEditCtrl'
})
});
Here are my controllers
var serverControllers = angular.module('serverControllers', ['utilitiesService']);
serverControllers.controller('serverListCtrl', function ($scope, $http) {
$http.get('/servers/getList').success(function (data) {
$scope.serverList = data;
});
});
serverControllers.controller('serverDetailsCtrl', function ($scope, $stateParams, $http) {
var serverName = $stateParams.serverName;
$http.get('/servers/getServerByName/' + serverName).success(function (data) {
$scope.server = data;
});
});
serverControllers.controller('serverEditCtrl', function ($scope, $stateParams, $http, $state, showAlertMessage) {
var serverName = $stateParams.serverName;
$http.get('/servers/getServerByName/' + serverName).success(function (data) {
$scope.server = data;
});
$scope.server.submitForm = function (item, event) {
console.log("--> Submitting Server Update");
//TIMDO: Verify all required fields have been included
var responsePromise = $http.post("/servers/postEdit", $scope.server, {});
responsePromise.success(function(dataFromServer, status, headers, config) {
showAlertMessage({
type: 'success',
title: 'Success',
message: 'Server information updated'
});
$state.go('clear');
});
responsePromise.error(function(data, status, headers, config) {
showAlertMessage({
type: 'error',
title: 'Success',
message: 'Server information updated'
});
});
}
});
Hmm, I'm probably misunderstanding your issue but I see at least one obvious difference between the look of your code and the look of mine.
My angular-ui-router links look like this:
<a ui-sref="reps-show({ id: rep.id })">{{rep.name}}</a>
The difference is the absence of braces around rep.id. So I wonder if changing this
<td><a ui-sref="details({ serverName: '{{server.name}}' })">Details</a></td>
to this
<td><a ui-sref="details({ serverName: server.name })">Details</a></td>
might do something for you.
That's probably not it but that's the first thing that came to mind for me.
I created simplified, but working version here. Because there is nothing obviously wrong. This example should at least help you to assure that:
All you are trying to do is supposed to be working.
Here are states:
// States
$stateProvider
.state('list', {
url: "/list",
templateUrl: 'tpl.list.html',
controller: 'serverListCtrl',
})
.state('edit', {
url: '/edit/:serverName',
templateUrl: 'tpl.html',
controller: 'serverEditCtrl'
})
Here controller of a list loading data
.controller('serverListCtrl', ['$scope', '$http', function ($scope, $http) {
$http.get('server.json').success(function (data) {
$scope.serverList = data;
});
}])
(server.json) - example of data
[
{"name":"abc"},
{"name":"def"},
{"name":"xyz"}
]
And the same template:
<li ng-repeat="server in serverList">
<a ui-sref="edit({ serverName: '{{server.name}}' })">
<button class="btn btn-lg btn-labeled btn-primary">
<span class="btn-label icon fa fa-edit"></span>
Edit {{server.name}}
</button>
</a>
</li>
All is working as expected. Check it here.
I want to contribute with another datapoint in-case some other folks arrive here with a similar question, as I did.
I was using the non-curly-brace version in my app, and it wasn't working. My specifics involve the InfoWindow in Google Maps. I believe there is a rendering order "issue" such that the data required for the ui-sref link doesn't exist, and when it does finally exist, it's never "re-rendered".
Original (non-working) version:
%h3
{{window_info.data.user.name || "Mystery Person"}}
%a.fa.fa-info-circle{ ui: { sref: 'users.show({id: window_info.data.user.id })' } }
%pre {{window_info.data.user.id | json}}
Working version:
%h3
{{window_info.data.user.name || "Mystery Person"}}
%a.fa.fa-info-circle{ ui: { sref: "users.show({id: '{{ window_info.data.user.id }}' })" } }
%pre {{window_info.data.user.id | json}}
I placed the %pre tag with the info to prove to myself that the datum was in-fact present (at least ultimately/eventually), but even still the original code for the link was not working. I adjusted my code to use the interpolated curly-brace version as per the OPs situation and it worked.
Conclusion: Your solution could depend on the way in which the parent component is handling rendering. Google Maps in this case is fairly notorious for being "funky" (technical term) with rendering, particularly in Angu-land.

Categories

Resources