如何将$ state变量传递给其他2个同级$ states? [英] How to pass $state variable into 2 other sibling $states?

查看:88
本文介绍了如何将$ state变量传递给其他2个同级$ states?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Plnkr:



设计说明:



我要解决的状态,组件,同级组件和视图混合问题是每个组件当任何状态更改时,应用程序始终刷新/重新启动。 $ state.go('dashboard'...



这不理想,我要做的是确保只有需要刷新的组件才能刷新。



IE:当我选择 Ticker Tag 时>我不希望 Feed 组件每次刷新,但是用户应该可以在 Feed 组件中执行操作,它将更新所有其他组件。



这就是为什么我创建一个容器状态来容纳两个仪表板 feed 状态。最初,我的一切都处于 dashboard 状态,并且任何时候都处于 $ state.go('dashboard'发生了 feed 组件也会刷新的问题。如果有解决此问题的更好方法lmk!: )



PS:开始学习使用ui-router消除对$ rootScope的依赖的状态管理。到目前为止,我的真实应用程序更加稳定,但是烦人的f每个组件都会刷新/重新启动。





< hr>

在下面的屏幕截图中,我可以清楚地看到正确的标记被传递到正确的$状态,但是 {{term}} 不会更新。







代码段(Plnkr中的完整代码)



app.container.html(容器状态)

 < div> 
< dashboard-module>< / dashboard-module>
< feed-module>< / feed-module>
<!-< div ui-view = dashboard>< / div>->
<!-< div ui-view = feed>< / div>->
< / div>

dashboard.html(显示板状态)

 < div class = jumbotron text-center> 
< h1>仪表板< / h1>
< / div>

< div class = row>
< tickers-module>< / tickers-module>

<!-标签组件在这里->
< div ui-view>< / div>

< view-module>< / view-module>

< social-module>< / social-module>
< / div>

^我使用< div ui-view>的原因; 上面的加载标签状态是,到目前为止,这是我可以初始化标签模块并显示来自行情收录器组件的标签列表的唯一方法。



tickers组件控制器:

  tickers.component('tickersModule',{
templateUrl:'tickers-module-template.html',
控制器:function($ scope,$ state){
console.log('Tickers component',$ state.params);
$ scope.tickers = [
{id:1,交易代码:'AAPL'},
{id:2,交易代码:'GOOG'},
{id:3,交易代码: 'TWTR'}
];

$ state.go('tags',{ticker:$ scope.tickers [0]}); //<-

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

^上面的< ---允许标签状态加载标签组件要素nt,然后根据代码行的状态连接标签列表

  var标签= angular.module('标签',['ui.router'])
标签.config(function($ stateProvider){

const标签= {
父对象:'容器',
名称:'tags',
网址:'/ tags',
参数:{
记号:{}
},
模板:'< tags- module>< / tags-module>',
控制器:function($ scope,$ state){
console.log('Tags state',$ state.params);
}
}

$ stateProvider.state(tags);
}}
tags.component('tagsModule',{
templateUrl:'tags-module-template.html',
controller:function($ scope,$ state){
console.log('Tags component',$ state.params);
const tags_model = [
{
ticker:'AAPL',
标签:[{ id:1,术语: iPhone 7},{id:2,术语: iPhone 8},{id:3,术语: Tim Cook}}
},
{
代码:'GOOG',
标签:[{id:4,条款:'Pixel'},{id:5,条款:'Pixel XL'},{id:6,条款:'Chrome图书'}]
},
{
ticker:'TWTR',
标签:[{id:7,term:'tweet'}},{id:8,term :'retweet'},{id:9,term:'moments'}]
}
];

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

$ state .params.ticker = $ state.params.ticker || {};
$ scope.tags_model = matc hTags($ state.params.ticker.ticker,tags_model)[0];

$ scope.clickTag = function(tag){
console.log('Tag clicked',$ state);
$ state.go('dashboard',{tag:tag});
}
}
});

标签列表中的点击功能:

  $ scope.clickTag = function(tag){
console.log('Tag clicked',$ state);
$ state.go('dashboard',{tag:tag});
}

socialMedia控制器:

  social.component('socialModule',{
templateUrl:'social-module-template.html',
控制器:函数($ scope,$ state){
console.log('Social component',$ state.params);
$ scope.term = $ state.params.tag.term;
}
});

viewHeader控制器:

  view.component('viewModule',{
templateUrl:'view-module-template.html',
控制器:function($ scope,$状态){
console.log('View component',$ state.params);
$ scope.term = $ state.params.tag.term;
}
} );






奇怪的组件倍增



在单击标签并破坏了social.component的内部之后,才注意到这一点。似乎仪表板组件正在重新渲染以代替标签组件,一瞬间:








已更新,通过添加 {refresh:true} 转到$ state.go中的标签。但是请注意,这仍然不能解决我的原始任务,即阻止feed.component刷新。因此,最终将使用服务。



解决方案

我已经更新了您的监听器



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



解决方案非常简单。在依赖项注入中使用 $ state 而不是使用 $ state ,这是一个单例,因此如果您像我一样引用它在更新的插件中:

  $ scope.params = $ stateParams 

然后显示值

  {{params.ticker.ticker }} 

是绑定到$ stateParams的2种方式,并在每次更改状态时相应地更新



---编辑---



我通过服务
添加了另一种解决方案 https://plnkr.co/edit/oQNAHv7tAS8LR9njOUAX?p=preview

  .service('awesomeTag',function($ rootScope){
var self = this;
$ rootScope。$ on( '$ stateChangeSuccess',function(_event,_toState,toParams){
self.tag = toParams.ticker.ticker
})

})


Plnkr: https://plnkr.co/edit/Brmcxd2LjGVJ6DXwuJtF?p=preview

Architecture:

$login -> $container (contains $dashboard and $feed), dashboard contains: $tickers, $tags, $viewHeader and $socialMedia components.

Goal:

tags needs to communicate and send a tag object into the viewHeader and socialMedia states.

Expected:

After Login, selecting a button in the Tags list should send that tag into the ViewHeader and SocialMedia states/components.

Results:

After Login, selecting a button in the Tags and going to $state dashboard the $states for the ViewHeader and SocialMedia refresh but the view model variable {{ term }} does not update with the appropriate tag in either component.

Design explanation:

The problem I'm trying to solve with a mix of states, components, sibling components and views is that every component in the app always refreshes/re-onInit when any state changes. $state.go('dashboard'...

This is not ideal, what I want is to make sure that only the components that need to refresh, refresh.

IE: When I select a Ticker or a Tag I do NOT want the Feed component to refresh every single time. However the user should be able to take an action in the Feed component and it will update all the others.

This is why I created a container state to hold both the dashboard and feed states. Originally I had everything in the dashboard state, and anytime $state.go('dashboard' happened the feed component would also refresh. If there is a better way to solve this issue lmk! :)

PS: Started learning about state management using ui-router to remove the reliance on $rootScope. So far my real app is much more stable, however has the annoying feature that every component refreshes/re-onInits.


In this screenshot below I can clearly see that the correct tag is being passed into the correct $states, but yet {{ term }} does not update.

Code snippets (Full code in Plnkr)

app.container.html (container state)

<div>
    <dashboard-module></dashboard-module>
    <feed-module></feed-module>
    <!--<div ui-view="dashboard"></div>-->
    <!--<div ui-view="feed"></div>-->
</div>

dashboard.html (dashboard state)

<div class="jumbotron text-center">
    <h1>The Dashboard</h1>
</div>

<div class="row">
  <tickers-module></tickers-module>

  <!-- Tags component goes here -->
  <div ui-view></div>

  <view-module></view-module>

  <social-module></social-module>
</div>

^ The reason I'm using a <div ui-view> above to load the tags state is that so far has been the only way I could initialize the tags module and show the tags list from the tickers component.

tickers component controller:

tickers.component('tickersModule', {
  templateUrl: 'tickers-module-template.html',
  controller: function($scope, $state) {
    console.log('Tickers component', $state.params);
    $scope.tickers = [
      { id: 1, ticker: 'AAPL' },
      { id: 2, ticker: 'GOOG' },
      { id: 3, ticker: 'TWTR' }
    ];

    $state.go('tags', { ticker: $scope.tickers[0] }); // <---

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

^ That <--- above allows the tags state to load the tags component element and wire up the tags list, based on the state of ticker

var tags = angular.module('tags', ['ui.router'])
tags.config(function($stateProvider) {

  const tags = {
    parent: 'container',
    name: 'tags',
    url: '/tags',
    params: {
      ticker: {}
    },
    template: '<tags-module></tags-module>',
    controller: function($scope, $state) {
      console.log('Tags state', $state.params);
    }
  }

  $stateProvider.state(tags);
})
tags.component('tagsModule', {
  templateUrl: 'tags-module-template.html',
  controller: function($scope, $state) {
    console.log('Tags component', $state.params);
    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; }
      });
    }

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

    $scope.clickTag = function(tag) {
      console.log(' Tag clicked', $state);
      $state.go('dashboard', { tag: tag });
    }
  }
});

The click function in the Tags list:

$scope.clickTag = function(tag) {
  console.log(' Tag clicked', $state);
  $state.go('dashboard', { tag: tag });
}

socialMedia controller:

social.component('socialModule', {
  templateUrl: 'social-module-template.html',
  controller: function($scope, $state) {
    console.log('Social component', $state.params);
    $scope.term = $state.params.tag.term;
  }
});

viewHeader controller:

view.component('viewModule', {
  templateUrl: 'view-module-template.html',
  controller: function($scope, $state) {
    console.log('View component', $state.params);
    $scope.term = $state.params.tag.term;
  }
});


Strange doubling up of components

Just noticed this, after clicking on a tag and breaking inside of the social.component. It looks like the dashboard component is being re-rendering in place of the tags component for a split second:


Updated, solved the issue here by adding { refresh: true } to $state.go in tags. Note however this still did not solve my original mission, which was preventing the feed.component from refreshing. So will end up using a service.

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

解决方案

I've updated your plunker

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

The solution is fairly simple. Instead of using $state use $stateParams in the dependency injection which is a singleton so if you reference it like I did in the updated plunker:

$scope.params = $stateParams

then the display value

{{params.ticker.ticker}}

will be 2 way bound to the $stateParams and update accordingly every time you change state

---edit---

I've added another solution through service https://plnkr.co/edit/oQNAHv7tAS8LR9njOUAX?p=preview

.service('awesomeTag', function($rootScope){
  var self = this;
  $rootScope.$on('$stateChangeSuccess', function(_event, _toState, toParams){
    self.tag = toParams.ticker.ticker
  })

})

这篇关于如何将$ state变量传递给其他2个同级$ states?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆