Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refresh ui-router view when state parameters change?

What's the correct way to update a ui-router view when state parameters change?

For example, if I've got a state like:

.state("page.view", {
    url: "/pages/:slug",
    views: {
        "": {
            controller: "PageCtrl",
            templateUrl: "page-view.html",
        },
    },
})

And an (incorrect) controller which looks like this:

.controller("PageCtrl", function($scope, $state) {
    $scope.page = loadPageFromSlug($state.params.slug);
})

How can I correctly load a new $scope.page when the $state.slug changes?

Note that the above does not work when moving from page to another because the controller is only run once, when the first page loads.

like image 713
David Wolever Avatar asked Nov 26 '14 21:11

David Wolever


2 Answers

I would do something like this:

.controller("PageCtrl", function($scope, $state) {
    $scope.$on("$stateChangeSuccess", function updatePage() {
        $scope.page = $state.params.slug;
    });       
});

I'd be curious if you find a better way - there may be some way to just watch the value of the state slug, but this is clean and clearly articulates what it is that you're watching for.

like image 162
Myk Avatar answered Oct 29 '22 17:10

Myk


I am really not fully sure, if I do not miss something here - but, based on the snippets shown in your question:

  • PageCtrl is related to state "page.view" and will be run as many times as "page.view" state is triggered
  • "page.view" state has declared param slug - url: "/pages/:slug",, which will trigger state change - whenever it is changed
  • If the above is true (if I do not oversee something) we can use stateConfig setting - resolve
  • there is no need to use $state.params. We can use $stateParams (more UI-Router way I'd personally say)

Well if all that is correct, as shown in this working plunker, we can do it like this

resolver:

var slugResolver = ['$stateParams', '$http'
                   , function resolveSlug($stateParams, $http){

  return $http
    .get("slugs.json")
    .then(function(response){
      var index = $stateParams.slug;
      return response.data[index];
    });

}];

Adjusted state def:

.state("page.view", {
    url: "/pages/:slug",
    views: {
      "": {
        controller: "PageCtrl",
        templateUrl: "page-view.html",
        resolve: { slug :  slugResolver },
      },
    },
})

And the PageCtrl:

.controller('PageCtrl', function($scope,slug) {
  $scope.slug = slug;
})

Check it all in action here

like image 2
Radim Köhler Avatar answered Oct 29 '22 17:10

Radim Köhler