How to prevent specific $state from refreshing when another $state updates

随声附和 提交于 2020-01-15 11:48:13

问题


https://plnkr.co/edit/bOZW1a9u62W1QA6cYjYj?p=preview

Expected

After Login all $states initialize, then after clicking a Ticker button, the only $states that should re-init are ticker, tags and social, but not feed.

Results

After Login all $states initialize, then after clicking a Ticker button all $states re-initialized. The feed should not.

How should the dashboard and feed module be architected to prevent this? At the moment I have the <feed-module></feed-module> inside the dashboard.html. Should it and the dashboard be further separated out in another in-between state/component? A container.component perhaps?

Full code

// Feed module
////////////////////////////////////////////////////////////////////////////////
var feed = angular.module('feed', ['ui.router'])

feed.config(function($stateProvider) {

  const feed = {
    name: 'feed',
    url: '/feed',
    templateUrl: '<em>Feed items go here.</em>'
  }

  $stateProvider.state(feed);

})

feed.component('feedModule', {
  templateUrl: 'feed-module-template.html',
  controller: function($scope, $state) {
    console.log('Feed init (only once)', $state.params);
  }
})

// RouterApp module
////////////////////////////////////////////////////////////////////////////////
var routerApp = angular.module('routerApp', ['ui.router', 'feed']);

routerApp.config(function($stateProvider, $urlRouterProvider) {

    $urlRouterProvider.otherwise('/login');

    const login = {
      name: 'login',
      url: '/login',
      templateUrl: 'login.html',
      bindToController: true,
      controllerAs: 'l',
      controller: function($state) {
        this.login = function() {
          $state.go('dashboard', {});
        }
      }
    }

    const dashboard = {
      name: 'dashboard',
      url: '/dashboard',
      params: {
        ticker: {},
        tags: {}
      },
      views: {
        '' : {
          templateUrl: 'dashboard.html',
        },
        'tickers@dashboard': {
          templateUrl: 'tickers-module-template.html',
          controller: function($scope, $state) {
            console.log('Tickers init', $state.params);

            $scope.tickers = [
              { id: 1, ticker: 'AAPL' },
              { id: 2, ticker: 'GOOG' },
              { id: 3, ticker: 'TWTR' }
            ];

            $scope.clickTicker = function(ticker) {
              console.log(' ')
              console.log('Ticker clicked!')
              $state.go('dashboard', { ticker: ticker });
            }
          }
        },
        'tags@dashboard' : {
          templateUrl: 'tags-module-template.html',
          controller: function($scope, $state) {
            const tags_model = [
              {
                ticker: 'AAPL',
                tags : [{ id: 1, term: 'iPhone 7' }, { id: 2, term: 'iPhone 8' }, { id: 3, term: 'Tim Cook' }]
              },
              {
                ticker: 'GOOG',
                tags : [{ id: 4, term: 'Pixel' }, { id: 5, term: 'Pixel XL' }, { id: 6, term: 'Chrome Book' }]
              },
              {
                ticker: 'TWTR',
                tags : [{ id: 7, term: 'tweet' }, { id: 8, term: 'retweet' }, { id: 9, term: 'moments' }]
              }
            ];

            function matchTags(ticker, model) {
              return model.filter(function(obj){
                if (obj.ticker === ticker) { return obj; }
              });
            }

            $scope.tags_model = matchTags($state.params.ticker.ticker, tags_model)[0];

            $scope.clickTag = function(tag) {
              $state.go('tags', { tag: tag });
            }

            console.log('Tags init', $state.params);
            // console.log(' Tags model', tags_model);
          }
        },
        'social@dashboard' : {
          templateUrl: 'social-module-template.html', 
          controller: function($state) {
            console.log('Social init', $state.params);
          }
        }
      }
    }

    $stateProvider
      .state(login)
      .state(dashboard);
});

Thoughts, would an architecture like this work? Basically login would navigate to a container state which will contain 2 components (dashboard and feed) each with their own internal states?


回答1:


I could resolve this issue depending on which state you're coming from. Based on the fact that you only want the feed to be loaded 'once' when dashboard is loaded, I'm checking the name of the previous state, and if it is not dashboard, only then I'll proceed with executing the rest of the controller code. Here is the plunker. Note that this is not very scalable approach if more states are added and if someone else has a better approach, I'd really like to see that.

I changed the controller code as follows:

feed.component('feedModule', {
  templateUrl: 'feed-module-template.html',
  controller: function($scope, $state) {
    var previousState = $state.params.previousState.name;
    if(previousState !== 'dashboard') {
      console.log('Feed init (only once)', $state.params); //do whatever u want here
    }
  }
});

I'm passing around previous state as params to other states like this:

controller: function($state) {
  this.login = function() {
    $state.go('dashboard', {previousState : { name : $state.current.name }})
  }
}

Look at the full plunker here to see if this helps your case!



来源:https://stackoverflow.com/questions/42844302/how-to-prevent-specific-state-from-refreshing-when-another-state-updates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!