Changing shared data in u-router

I want to ask you about data exchange between states in ui-router. This is my example $ stateProvider

$stateProvider.state('start',{
    url:"/inicio",
    templateUrl:"./app/templates/start.html",
    abstract: true,
    data:{
        title: 'Hello world'
    },
    controller: 'aplicacionController',

}).state('start.App',{
    url:"/aplicacion",
    templateUrl:"./app/templates/escritorio.html"
}).state('start.App.onlyMenu',{
    url:"/ms",
    views:{
        'menu':{
            templateUrl:"./app/templates/menu.html",
            controller:'menuController'
        },
        'mainFrame':{
            templateUrl: './app/templates/whiteBoard.html',
            controller:'whiteBoardController'
        }
    }
}).state('start.app.JqPlotCharts',{
    url:"/jqp",
    views:{
        'menu':{
            templateUrl:"./app/templates/menu.html",
            controller:'menuController'
        },
        'mainFrame':{
            templateUrl: './app/templates/jqplotcharts.html',
            controller:'jqplotCtrl'
        }
    }
});

      

As you can see, I have a parent state called start with a data field that has a title property set to "Hello world". AplicacionController has two missions: first you need to read the value of the title and store it in the $ scope variable called title:

$scope.title = $state.current.data.title;

      

And the second is to see if the title changes, and if it does, update the value of $ state.current.data.title:

$scope.$watch('title', function(){
    $state.current.data.titulo = $scope.title;
});

      

Of course, inside the start.html template, I have a small form to change this value:

<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <a class="navbar-brand" href="#">{{title}}</a>
    </div>

   <!-- Collect the nav links, forms, and other content for toggling -->
   <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <form class="navbar-form navbar-left" role="search">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search" ng-model="title">
        </div>
      </form>
   </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>

      

My intent is that all the child states read the header value and when it changes from the parent template, the value is also updated in the child states. However, this never happens. The value is updated in the parent state, but never in the children.

What am I missing?

thank

+3


source to share


1 answer


I would try to explain why this requirement should be treated differently.

First, the .data

state parameter (see Attach custom data to state objects ) should be considered as part of the configuration. Value: readonly, constant. In addition, as inheritance shows .data

, there is some smart mechanism to provide almsot with the opposite functionality than what is required above:

Inherited user data

Child states inherit data properties from the parent state (s), which they can overwrite.

$stateProvider.state('parent', {
      data:{
         customData1:  "Hello",
         customData2:  "World!"
      }
   })
   .state('parent.child', {
      data:{
         // customData1 inherited from 'parent'
         // but we'll overwrite customData2
         customData2:  "UI-Router!"
      }
   });

$rootScope.$on('$stateChangeStart', function(event, toState){ 
    var greeting = toState.data.customData1 + " " + toState.data.customData2;
    console.log(greeting);

    // Would print "Hello World!" when 'parent' is activated
    // Would print "Hello UI-Router!" when 'parent.child' is activated
})

      

As we can see, this is what we can do with our state

custom .data

object configuration .

But how to solve the problem with us? Well, there is a really native solution Angular JS

:



Service .

Such an object will act as a single object. We can do this, we can put it in $rootScope

... we can do a lot. But basically we can use it for data exchange. See a similar example and solution here:

And this developed service is called Settings

.factory('Settings', function(){
  return {
    Property1: null,
    Property2: null,
    ...
  };
})

      

A plunker of this example.

+3


source







All Articles