Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - Angular UI-Router reload only nested view, not parent

I know this is rather long, but I need to provide some context before my main question. I am creating a page that will be split into two columns. Here is the ui-router code:

  $urlRouterProvider.otherwise("/projects/edit")

  $stateProvider
    .state('projects', {
      url: "/projects",
      template: "<div ui-view></div>"
    })

    .state('projects.edit', {
      resolve: {
        test: function(){
          console.log('projects.edit resolve called')
        }
      },
      url: "/edit",
      templateUrl: "projects.html",
      controller: function($scope, $state){
        $state.go('projects.edit.surveys')

        $scope.transitionToOtherRoute = function () {
            $state.transitionTo('otherRoute')
        }
      }
    })
    .state('projects.edit.surveys', {
      resolve: {
        items: function(){
          var randomNumberArray = [1,2,3,4,5,6]
          //this will just shuffle the array
          for(var j, x, i = randomNumberArray.length; i; j = Math.floor(Math.random() * i), x = randomNumberArray[--i], randomNumberArray[i] = randomNumberArray[j], randomNumberArray[j] = x);
          return randomNumberArray
        }
      },
      url: "/surveys",
      views: {
        "viewA": { 
            templateUrl: "projects.surveys.html",
            controller: function($scope, items, $state){
            $scope.items = items
            $scope.addSurvey = function(){
              $state.transitionTo($state.current, $state.params, { reload: true, inherit: true, notify: true })
            }
          }
        }
      }
    })
    .state('otherRoute', {
      url: "/otherRoute",
      templateUrl:"otherRoute.html"
    })

Basically, the user will be transitioned to the projects.edit state, which has a template that looks like this:

<h3>PROJECTS.HTML PARTIAL</h3>
<div class="row">
  <div class="col-md-6">
    Input Text: <input type="text"><br>
    <button type="submit" class="btn btn-primary" ng-click="updateProject()">Go to otherRoute</button>
  </div>
  <div class="col-md-6">
    <a ui-sref=".surveys"></a>
    <div ui-view="viewA"></div>
  </div>
</div>

The user will be presented with two columns. The left column will just have an input field and button, which when pressed will transition the user to the otherRoute state.

When we transition to the projects.edit state, it's controller will call $state.go('projects.edit.surveys'), which will set up it's nested view in the right column. The projects.edit.surveys state will first resolve an array of numbers in a random order, which it will pass into the controller as a parameter called items. The projects.surveys.html partial will then be placed in the right column. It will show the list of numbers in a random order and have a button, which calls $state.transitionTo($state.current, $state.params, { reload: true, inherit: true, notify: true }). This button will reload the projects.edit.surveys state. The user will see the numbers in a different order, and any text in the input field in the left column will disappear.

This can be seen in action in this Plunker: http://plnkr.co/edit/SK8hjMpw6kvPiTdVeEhz?p=preview

This all leads to my question: how can I only reload the content of the right column ie the nested view (projects.edit.surveys), without reloading the parent view (projects.edit)? I would like to be able press the button in the right column and only re-sort the numbers, which is done in projects.edit.surveys state's resolve, and not clear the input field in the left column (and not call the resolve methods in projects.edit). In other words, I'd like only refresh the right column projects.edit.surveys state, without affecting anything in the left hand projects.edit state.

Any help would be greatly appreciated!!!

like image 381
andrew Avatar asked Aug 06 '14 16:08

andrew


1 Answers

There is a plunker with one modification. Instead of using very extreme setting reload: true, we can profit from native ui-router desing:

reload the state in case its declared param has changed

So, this would be the new state and controller definition:

.state('projects.edit.surveys', {
      resolve: {
        ... // unchanged
      },
      // here we declare param trigger
      url: "/surveys/{trigger}",
      views: { 
      '' : { 
            templateUrl: "projects.surveys.html",
            controller: function($scope, items, $state){
              $scope.items = items
              $scope.addSurvey = function(){

                // here we copy current params
                var params = angular.copy($state.params);
                // do some tricks to not change URL
                params.trigger = params.trigger === null ? "" : null;
                // go to the same state but without reload : true
                $state.transitionTo($state.current, params, { reload: false, inherit: true, notify: true })
              }
            }
        }
      }
    })

From a user perspective, param is changing but not its visibility - it is null or string.Empty ... Check that adjustment and a bit more native ui-router solution here

like image 106
Radim Köhler Avatar answered Nov 06 '22 04:11

Radim Köhler