1

I have a layout set up for one of my pages that is then seeded with a ton of little views that I use to populate with date. My states currently looks like so:

  .state('eventLayout', {
    templateUrl: 'partials/layouts/event.html',
    controller: 'EventCtrl',
  })
  .state('event', {
    parent: 'eventLayout',
    url: '/event/{eventUrl}',
    views: {
      'event.video': {
        templateUrl: 'partials/views/event.video.html'
      },
      'event.info': {
        templateUrl: 'partials/views/event.info.html'
      },
      'card.event': {
        templateUrl: 'partials/views/card.event.html'
      },
      'card.clip': {
        templateUrl: 'partials/views/card.clip.html'
      },
      'card.upcoming': {
        templateUrl: 'partials/views/card.upcoming.html'
      },
      'card.banner': {
        templateUrl: 'partials/views/card.banner.html'
      },
      'card.comment': {
        templateUrl: 'partials/views/card.comment.html'
      },
      'card.notification': {
        templateUrl: 'partials/views/card.notification.html'
      },
      'card.cube': {
        templateUrl: 'partials/views/card.cube.html'
      },
      'card.mix': {
        templateUrl: 'partials/views/card.mix.html'
      },
      'card.score': {
        templateUrl: 'partials/views/card.score.html'
      },
      'card.sponsor': {
        templateUrl: 'partials/views/card.sponsor.html'
      },
      'card.nobroadcasters': {
        templateUrl: 'partials/views/card.nobroadcasters.html'
      },
      'card.link': {
        templateUrl: 'partials/views/card.link.html'
      },
      'card.suggest': {
        templateUrl: 'partials/views/card.suggest.html',
        controller: 'SuggestblockCtrl'
      },
      'card.footer': {
        templateUrl: 'partials/views/card.footer.html'
      }
    }
  })

As you can see the parent layout holds my Controller for the page which is called EventCtrl . Now I would expect that all the views now have access to this controller, but that doesn't seem to be the case. Instead I have to wrap the main parent template from eventLayout in a div where I then just use the old school:

 <div ng-controller="EventCtrl"></div>

I'd like to at least understand why this is happeneing and what the proper method is to make sure all views have access to the states main controller. Thanks!

EDIT:

To add more context to how im using the views in my current app I have detailed the current set-up below.

From the file partials/layouts/event.html in parent $state eventLayout

<div ng-controller="EventCtrl">
<div ui-view="event.video"></div>
  <div ng-repeat="activity in activities.results">
    <div ng-if="activity.card_type == 'event'" ui-view="card.event"></div>
    <div ng-if="activity.card_type == 'clip'" ui-view="card.clip"></div>
    <div ng-if="activity.card_type == 'upcoming'" ui-view="card.upcoming"></div>
  </div>
</div>
</div>

As you can see a views are nested within the parent layout. I'm having to wrap it all with ng-controller="EventCtrl" in order to allow each view access to its scope.

Mr. BigglesWorth
  • 1,530
  • 3
  • 18
  • 33
  • I little more context would be helpful. Could you give us an example of how you are implementing the children views and the approach you are using to access the parent data? – Rob Sep 23 '14 at 21:56

1 Answers1

3

The overall angular's ui-router design, is about the view / $scope inheritance - not base controller accesibility. The detailed info could be found here:

Scope Inheritance by View Hierarchy Only

small cite:

Keep in mind that scope properties only inherit down the state chain if the views of your states are nested. Inheritance of scope properties has nothing to do with the nesting of your states and everything to do with the nesting of your views (templates).

It is entirely possible that you have nested states whose templates populate ui-views at various non-nested locations within your site. In this scenario you cannot expect to access the scope variables of parent state views within the views of children states...

Also these are good reading, which content would be hardly any better explained here:

So, let's summarize a bit.

1) We know, that from any template we can access only its own $scope.
2) What is available in the view/template $scope, is a job of its Controller which can extend it with some functions, objects, etc.
3) If any parent controller (from view-nesting perspective) will inject anything into its own/parent scope - we will have access to it as well (so called prototypical inheritance)

Having this, we can create an Events object in the parent $scope, managed by EventCtrl - and consume it in any a child view template:

// the reference (reference to object Events) 
// to be shared accross all child $scopes
$scope.Events = {};

// objects
$scope.Events.MyModel = { FirstName: "....

// functions
$scope.Events.save = function () {....

And now in any child template we can use it like this

<div>{{Events.MyModel.FirstName}}</div>

Another technique would be to place the controller into $scope's Events object:

$scope.Events = this; // controller

And then have full access to controller's methods, properties...

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Excellent answer, Radim. UI-Router architecture can be confusing for those coming from plain-old-angular ng-controller style. This overview is very concise and clear. – Chris T Sep 24 '14 at 15:35
  • @radim-köhler I think i got it (although I need to read through it a few more timea). The odd issue for me was that wraping my entire **event.html** from the parent state of **eventLayout** in `
    ` allowed me access to all scopes within the controller. In my brain it seems like attaching that controller to the state like my example above should basically be doing the same thing. Given my understanding of what you're saying, my exmaple is showing a parent with no nested views and a child with several. Could I then just place the control on the child state?
    – Mr. BigglesWorth Sep 24 '14 at 18:10
  • @RadimKöhler As another follow up I edit my example to show a bit more on how its being used. With this use case shouldnt I be able to retrieve the scopes created from the controller from any view if I attach it to the parent state? – Mr. BigglesWorth Sep 24 '14 at 18:26
  • @Mr.BigglesWorth, I am really not sure what you try to achieve. Maybe you should firstly read more about UI-Router, to understand what you can get. Mostly how could **Multi-Views** and **Nested-States** work for you. Here I put together all essential **links [where to start](http://stackoverflow.com/a/20581135/1679310)**. And also, I created some [plunker for you here](http://plnkr.co/edit/g5LXtyGM1Nom76keis5f?p=preview) which shows what I described above, *while I am really not sure what you do ;(* – Radim Köhler Sep 25 '14 at 05:22