Plnkr: https://plnkr.co/edit/Brmcxd2LjGVJ6DXwuJtF?p=preview
$login
-> $container
(contient $dashboard
et $feed
), le dashboard
contient: $tickers
, $tags
, $viewHeader
et $socialMedia
.
tags
doivent communiquer et envoyer un objet tag dans les viewHeader
et socialMedia
.
Après la connexion , sélectionner un bouton dans la liste des balises doit envoyer cette tag
dans les états / composants ViewHeader et SocialMedia .
Après la connexion , en sélectionnant un bouton dans les balises et en allant sur le dashboard
$ state les états $ pour le rafraichissement ViewHeader et SocialMedia mais la variable modèle {{ term }}
ne se met pas à jour avec la balise appropriée dans l'un ou l'autre composant.
Le problème que j'essaie de résoudre avec un mélange d'états, de composants, de composants et de vues de frères et sœurs est que chaque composant de l'application est toujours actualisé / réinitialisé lorsque l'état change. $state.go('dashboard'...
Ce n'est pas idéal, ce que je veux, c'est de s'assurer que seuls les composants qui doivent être rafraîchis, rafraîchissent.
IE: lorsque je sélectionne un Ticker ou une étiquette, je ne souhaite PAS que le composant Feed soit actualisé toutes les fois. Toutefois, l'utilisateur devrait pouvoir prendre une action dans le composant Feed et il mettra à jour tous les autres.
C'est pourquoi j'ai créé un état de container
pour tenir à la fois le dashboard
et feed
états d' feed
. À l'origine, j'avais tout dans l'état du dashboard
et, à tout moment, $state.go('dashboard'
est arrivé, le composant d' feed
serait également actualisé. S'il y a un meilleur moyen de résoudre ce problème, lmk! 🙂
PS: a commencé à apprendre sur la gestion de l'état en utilisant ui-router pour supprimer la dépendance sur $ rootScope. Jusqu'à présent, ma véritable application est beaucoup plus stable, mais la fonctionnalité ennuyeuse est que chaque composant actualise / re-onInits.
Dans cette capture d'écran ci-dessous, je peux clairement voir que la tag
correcte est passée dans les états $ corrects, mais pourtant {{ term }}
ne se met pas à jour.
Extraits de code (code complet dans Plnkr)
App.container.html (état du conteneur)
<div> <dashboard-module></dashboard-module> <feed-module></feed-module> <!--<div ui-view="dashboard"></div>--> <!--<div ui-view="feed"></div>--> </div>
Dashboard.html (état du tableau de bord)
<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>
^ La raison pour laquelle j'utilise une <div ui-view>
ci <div ui-view>
dessus pour charger l'état des balises est que jusqu'à présent a été la seule façon d'initialiser le module tags et de montrer la liste des balises du composant tickers.
Contrôleur de composant tickers:
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 }); } }
^ Cela <— ci-dessus permet à l'état des balises de charger l'élément composant des balises et de filer la liste des balises, en fonction de l'état du 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 }); } } });
La fonction de clic dans la liste des tags:
$scope.clickTag = function(tag) { console.log(' Tag clicked', $state); $state.go('dashboard', { tag: tag }); }
Contrôleur socialMedia:
social.component('socialModule', { templateUrl: 'social-module-template.html', controller: function($scope, $state) { console.log('Social component', $state.params); $scope.term = $state.params.tag.term; } });
Contrôleur viewHeader:
view.component('viewModule', { templateUrl: 'view-module-template.html', controller: function($scope, $state) { console.log('View component', $state.params); $scope.term = $state.params.tag.term; } });
Il suffit de remarquer ceci, après avoir cliqué sur une étiquette et la rupture dans le social.component. Il semble que le composant du tableau de bord est en train de redistribuer à la place du composant tags pour une fraction de seconde:
{ refresh: true }
à $ state.go dans les tags. Notez cependant que cela ne résolut toujours pas ma mission initiale, ce qui empêchait le feed.component de se rafraîchir. Cela finira par utiliser un service.
J'ai mis à jour votre plunker
https://plnkr.co/edit/ywyH7wOmR6loNiAkH9Yb?p=preview
La solution est assez simple. Au lieu d'utiliser $state
use $stateParams
dans l'injection de dépendance qui est un singleton, alors si vous le référez comme je l'ai fait dans le plunker mis à jour:
$scope.params = $stateParams
Puis la valeur d'affichage
{{params.ticker.ticker}}
Sera lié à 2 voies avec les $ stateParams et la mise à jour en conséquence chaque fois que vous modifiez l'état
—modifier—
J'ai ajouté une autre solution via le 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 }) })
J'ai mis à jour votre plunker ici . Le problème dans votre code était ici:
view.component('viewModule', { templateUrl: 'view-module-template.html', controller: function($scope, $state) { console.log('View component', $state.params); $scope.term = $state.params.tag.term; //culprit line } });
Ce que vous devez plutôt faire, c'est utiliser $ stateParams pour récupérer les paramètres. J'ai changé le code dans viewModule comme suit:
controller: function($scope, $stateParams) { console.log('View component', $stateParams); $scope.tickerObj = $stateParams; }
Et ensuite, a mis à jour le view-module-template.html
pour utiliser tickerObj comme suit:
{{ tickerObj.ticker.ticker }}
Même chose pour le module social.
Un exemple simple pour comprendre comment cela fonctionne est le suivant:
$stateProvider.state('stateName', { url: '/stateName', controller: 'myCtrl', params: { //this can also be used to give default values for route params obj: null } }); function myCtrl($stateParams) { console.log($stateParams); //will display the obj parameter passed while transitioning to this state } $state.go('stateName', {obj:yourObj}); //passing obj as param to stateName state, this can be retrieved using $stateParams.
Ceci est similaire au problème qui se passe dans votre dernière question.
J'ai remarqué un autre problème avec votre code. En cliquant sur l'une des étiquettes comme retweet, moments, tweet, il change le ticker à "AAPL" à nouveau. Ce comportement est-il prévu? (Si ce n'est pas le cas, cela se produit car lorsque vous passez à l'état du tableau de bord après avoir cliqué sur un ticker, tous les modules sont réinitialisés. La ligne qui provoque ceci est
$state.go('tags', { ticker: $scope.tickers[0] });
J'espère que cela t'aides!
Mettre à jour:
J'ai mis à jour le plunker ici . J'ai commenté cette ligne:
$state.go('tags', { ticker: $scope.tickers[0] });
Qui était par défaut fixer ticker à apple chaque fois que nous venions à l'état du tableau de bord. Je transmet également le code et l'objet de l'étiquette à la fois à la fois à l'état de la vue et à l'état social. Si vous regardez la console, vous pouvez obtenir les valeurs correctes pour les étiquettes et les tickers sur ces deux états. Faites-moi savoir si cela fonctionne pour vous.
Vous pouvez vérifier que les valeurs de l'étiquette et du ticker sont transmises à la vue et aux composants sociaux en regardant les journaux de la console. Voici un extrait:
En publiant ceci parce que c'est la bonne façon de résoudre ce problème, et correctement architecte l'application:
https://plnkr.co/edit/MztpsHj9qoRCFUDrREH7?p=preview
Ici, j'utilise correctement les états enfants et les vues nommées.
Container-template.html
<div> <div class="fl w100"> <em>Container component module scope</em> </div> <div ui-view="dashboard"></div> <div ui-view="feed" class="fl"></div> </div>
Les tags indiquent
const tags = { name: 'container.dashboard.tickers.tags', url: '/tags', params: { ticker: {}, tag: {} }, views: { 'tags' : { templateUrl: 'tags-list.html', controller: function($scope, $state) { console.log('tags-list controller', $state) $scope.ticker = $state.params.ticker;
Et la navigation d'état à children.child déclare:
$scope.clickTicker = function(ticker) { $state.go('container.dashboard.tickers.tags', { ticker: ticker }); }