I have a view where it is possible to have different objects loaded based on an ID. It is a get request and the controller or state should not entirely reload. I am using ui-router and I've come across the "reloadOnSearch" property. Setting this to false should not reload the controller based on the params, it should only reload on state change. However this is not working. Here is my config function:
var MAIN_CONFIGURATION = {
Setup: function(app) {
app.config(["$stateProvider", "$urlRouterProvider", function($stateProvider, $urlRouterProvider) {
$stateProvider.state("myState",
{
url: "/mystate/:id",
reloadOnSearch: false,
templateUrl: "/app/Main/templates/test.html?version=0.0.0.0001",
controller: testCtrl
});
$urlRouterProvider.when("", ["$state", function($state) {
$state.go("myState");
}]);
}]);
.
.
.
}
};
Below is my partial HTML:
<tr ng-repeat="item in items" ui-sref="myState({id: '{{item.ID}}'})">
<td>{{item.FirstName}}</td>
<td>{{item.LastName}}</td>
</tr>
Basically a bunch of table rows are generated and when a row is clicked on, I am expecting the controller to not entirely reload. However, it does. Even when pressing the back and forward buttons on the browser, it is being reloaded.
I have no idea what I am doing wrong, any help would be appreciated.
Actually I just figured it out. The route must contain "query" parameters. Thus I cannot use "/mystate/:id". I should instead use "/mystate?id".
Related
I understand this has been asked and answered in multiple posts but I have attempted the solutions and still can't quite get there yet.
I have a few components that I'm routing between with ui-router and one is a contact form which, if a user enters data to and moves to another route then back to the contact form the state is reloaded and the form contents gone.
I saw another way of doing this by having a parent state and child states but couldn't recreate this in my code.
Maybe there's a simpler solution by using ui-router-extras with the sticky option although I attempted this and could't get it working either. I'll post the code as it works now.
(function () {
angular.module('personalPortfolio')
.config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('about', {
sticky: true,
url: '/about',
template: '<pg-about></pg-about>'
})
.state('development', {
sticky: true,
url: '/work',
template: '<pg-dev></pg-dev>'
})
.state('contact', {
sticky: true,
url: '/contact',
template: '<pg-contact></pg-contact>'
});
$urlRouterProvider.otherwise('/about');
}]);
})();
You can create a service when You will store unsaved form data.
Pretty new to Angular, I am sure I'm missing something obvious here. I am using ui-router.
I want to provide a link to my clients so that they can click the URL link and visit the web app with the appropriate partial. I also want to be able to pass in parameters. Here's how I approached this (kind of hokey). This is in my main controller:
var pNumber = $location.search().number;
if (!(pNumber == null || pNumber == "")){
$state.go('view-ticket');
}
Here is my app.js:
$stateProvider
.state('home', {
url: "/",
templateUrl: 'partials/welcome-screen.html',
controller: 'mainPageController'
})
.state('submit-ticket', {
url: "/submit-ticket",
templateUrl: 'partials/ticket-submit.html',
controller: 'TicketSystemTestCtrl'
})
.state('view-ticket', {
url: "/view",
templateUrl: "partials/ticket-central.html",
controller: 'TicketCentralCtrl'
})
The logic is this: If the URL contains a param 'number' inject ticket-central.html partial.
However, when I run this in the debugger, it seems the first part of the code got executed before it loads the welcome-screen.html partial. How to solve this?
EDIT: I am trying to type this into the URL: http://localhost/techsupport/view and I want it to load the ticket-central.html partial into the main view. However, it won't work.
if i understand correctly all you want to do is to provide a possibility to 'deep-link' to the 'view-ticket' state.
for this search params are not the ideal solution as they are optional, just use path variables:
.state('view-ticket', {
url: '/view/:ticketNumber,
template: 'partials/ticket-central.html',
controler: 'TicketCentralCtrl'
})
also don't use the $location service if you don't really have to, have a look at $stateParams
here is a small plunkr with a welcome and a ticket state
launch the preview in a separate window to see how the url changes - you can also refresh on each page and the correct state will be loaded
https://plnkr.co/edit/r3UcYbfwET0OVwkd77Rv
I created this small app where I have following states:
restricted.route.js
$stateProvider.state('restricted', {
url: '/restricted',
templateUrl: 'app/restricted/restricted.html',
abstract: true
});
pages.route.js
$stateProvider.state('restricted.pages', {
url: '/pages',
templateUrl: 'app/restricted/pages/pages.html',
controller: 'pagesController',
controllerAs: 'vmPages'
});
detail.route.js
$stateProvider.state('restricted.pages.detail', {
url: '/:id',
controller: 'pageDetailController',
controllerAs: 'vmDetail',
templateUrl: 'app/restricted/pages/detail/detail.html'
});
app.run.js
$urlRouterProvider.otherwise('/restricted/dashboard');
When I load the URL #/restricted/pages everything works fine. Controller is loaded and view is shown.
When I load the URL #/restricted/pages/1 the controller and view from the state 'restricted.pages' is loaded and executed.
The state is clearly recognized, because the $urlRouterProvider.otherwise is not executed.
Does anyone have an idea what I'm doing wrong here?
Thanks!
Is it intentional to have the details as a substate of the pages (list?) state? If so, you need to place an <div ui-view></div> into the template named app/restricted/pages/pages.html.
If that was not your intention, I recommend to rename the detail state to something like restricted.pages_detail as every dot introduces a nested level in the state definitions.
I think your issue lies in the HTML, the nested state should be loaded in a ui-view tag on the parent element.
I am not sure what the problem is, im assuming its something with the way my angular routing is? If anyone could help that would be very appreciated.
This is my controller, the console log here actually prints.
app.controller('ClientCtrl',['$http','$scope',
'$stateParams',function($http,$scope, $stateParams){
var clientid = [$stateParams.id];
var client = this;
client.infos = []
$http.get('../client.JSON').success(function(data){
client.infos = data;
console.log(client.infos)
});
}]);
This is my routes, im using ui.router, since im using angular. the client route is the one causing problems.
planoxApp.config(['$stateProvider','$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/templates/index.html',
controller: 'MainCtrl',
})
.state('clients', {
url: '/clients/{id}',
templateUrl: 'clientsmain.html',
controller: 'ClientCtrl'
})
.state('photoplans', {
url: '/photoplans/:id',
templateUrl: 'photoplanmain.html'
});
}])
This is the html file thats causing me problems
<h1>Hi! </h1>
<div class="col-sm-6" ng-repeat="info in client.infos" >
<p>{{info.active}}</p>
</div>
<script> console.log("this sucks") console.log(client.infos)</script>
And this is the console right now
I have tried everything i can think of to get this to work, but nothing works currently. As you can see angular is not throwing errors, but nothing is console logging from this page nor is the ng-repeat working. Any help is greatly appreciated, thanks in advance.
You have already printed a result from the angular controller in console its there in screen shot.
Seems like you should us controllerAs alias there for controller, you could declare alias inside your state itself like by doing controller: 'ClientCtrl as client'
Markup
<h1>Hi! </h1>
<div class="col-sm-6" ng-repeat="info in client.infos" >
<p>{{info.active}}</p>
</div>
State
.state('clients', {
url: '/clients/{id}',
templateUrl: 'clientsmain.html',
controller: 'ClientCtrl as client'
})
Update
You can not load script from the partials, they will never get readed when they are loaded through the partial html. Though using console.log(client.infos) never make sense how can you think of angular context will available for the global script.
If you want it something like this then you could take a look at this thread, but my personal advice is you shouldn't go for this.
In my angular project, when changing the path with $location.path('/foobar') the destination view is displayed but the data aren't reloaded (typically after saving an item and going back to the list, the list is not updated).
I tried to add $route.reload() or $scope.apply(), but nothing change.
I don't know what's wrong or missing to make this work.
UPDATE
$location.url() doesnt' work either
I'm using angular 1.2.26
UPDATE 2 - ANSWER
Ok, after a lot of comments and answers, I think it's time to end this.
I didn't think it would have been a so complicated question.
So, my conclusion, giving all you said is :
Giving simple example of #yvesmancera, the default behavior of the controller is to reload itself
In a complex controller with a resource factory and some REST calls, any save or update action should also manually update the list reference, or trigger a full reload of the list
All of you gave me some good advices, so thank you.
Use $window.location.href. to reload the page. I just check on $location document:
Page reload navigation
The $location service allows you to change only the URL; it does not allow you to reload the page. When you need to change the URL and reload the page or navigate to a different page, please use a lower level API, $window.location.href.
Example:
$window.location.href = "/your/path/here";
I had the same problem just yesterday, if you try to navigate to the same path you're already in, angular won't try to reload the view and controller. What fixed it for me is appending a "/" at the end of each route in $routeProvider, e.g:
$routeProvider
.when('/', {
templateUrl: 'views/home.html',
controller: 'HomeCtrl'
})
.when('/About/', {
templateUrl: 'views/about.html',
controller: 'AboutCtrl'
})
.when('/Contact/', {
templateUrl: 'views/contact.html',
controller: 'ContactCtrl'
})
Edit
Here is a working plunkr with angular 1.2.26
http://plnkr.co/edit/jkGKKCp0djN6Jvy2fIRd?p=preview
Pseudo Code:-
app.controller('myController', ['$scope', '$location','$http', 'ItemListService'
function($scope, $location, $http, ItemListService){
$scope.data = function(){
ItemListService.getAllItems(); //get all the items;
};
$scope.saveMethod = function(item){
$scope.data = ItemListService.save(item); //this is the refresh part, return data through save method. Pull the latest data and bind it to the scope.
$location.path('/fooView'); //dont think you even need this if you are entering data in a modal sorta thing, which on the same view.
}
}]);
You service should look like,
app.service('ItemListService', function(){
this.getAllItems = function(){
//get the items from itemList
//return all the items
}
this.save = function(item){
//save the item in itemList
//**return all items again, call getAllItems here too.
}
});
Hope this helps!!
You can switch https://github.com/angular-ui/ui-router it has method $state.reload() which can re-initialize whole controller.
If you dont want to switch ther is problem that controller is still living but you can implement after save
$rootScope.$broadcast('data:updated', $scope.data);
then wrap method of loading data in controller to function and then you can push new data to existing list / or make ajax reload
$rootScope.$on('data:updated',function(listener,data) {
$scope.data.push(data);
});
$rootScope.$on('data:updated',function()
{
callAjax.then(function(data) {
$scope.data = data;
}
});
https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on
Try $scope.dataModel.$save(); $location.url('/foobar'); Another reason might solve the problem is: when you redirect to /foobar, the controller of foobar should have a AJAX call to your server to load the new data. And you should use angular factory to make your AJAX calls. If it is still not working, can you give more information about the version of the angular you are using, as well as your backend framework and database.
$location.path("/login");
$timeout(() => $scope.$apply(), 1000);
works for me