-1

I'm using UI-Router for Angular and I have separated views for my app: sidebar and main. Now i need to change some class in main view after some action that does in sidebar view.

So, this is my code:

config

.state('app.area', {
    url: '/area/:areaId',
    views: {
        '@': {
            template: require('./app/generic/genericWithSidebar.html'),
            controller: 'AreaCtrl'
        },
        '[email protected]': {
            template: require('./app/area/_area.html'),
            controller: 'AreaCtrl',
            controllerAs: 'CTRL',
        },
        '[email protected]': {
            template: require('./app/area/_sidebar.html'),
            controller: 'AreaCtrl',
            controllerAs: 'CTRL',
        }
    },

controller

class AreaCtrl {
    constructor($scope) {
        "ngInject";

        this.$scope = $scope;
        this.$scope.descriptionIsActive = false;
    }

    showAreaDescription() {
        this.$scope.descriptionIsActive = !this.$scope.descriptionIsActive;
    }
}

export default AreaCtrl;

and views for sidebar and main

// sidebar view
<span ng-click="CTRL.showAreaDescription()">show more</span>
// main view
<div ng-class="{'active': CTRL.descriptionIsActive}"></div>

I need to communicate between views, not controllers, i have one controller.

11
  • Need to be aware that each view initializes a new instance of AreaCtrl each with it's own scope Commented Feb 9, 2017 at 13:38
  • @charlietfl So, what should i do? Should i remove controller definition for view and leave only for parent? Commented Feb 9, 2017 at 13:40
  • probably .....yes. Not really enough known about the app though Commented Feb 9, 2017 at 13:41
  • You can use $broadcast for that ype of situation. Commented Feb 9, 2017 at 13:42
  • Possible duplicate of angularjs: using service to communicate between controllers Commented Feb 9, 2017 at 13:56

4 Answers 4

1

The "correct" solution depends on what it is that changed in your main view that causes a change in the navigation.

As I just answered here, it is generally a bad sign if you need controllers to "talk" to each other. This often means that you should have a service that takes care of the data/state that you want to bind to in both views.

If, however, your change is really just a global cosmetic navigational thing (I can not think of an example but I do not want to say that thats impossible), a "global" NavigaitonController (on your body for example) might be correct. I doubt it though.

So my suggestion is: Think about what data causes the change, handle the state of that data in its own service and bind to that service property where you need it.

Sign up to request clarification or add additional context in comments.

1 Comment

So, this ok that i've used one, other controller for action in sidebar? In that case everything is working fine. Thx from the top for the advice.
1

You could define your controller outside the views option so that it will only load once on state load.

stateProvider.state("app.area",{
   url:'/app.area',
   templateUrl: 'app_area_frame.html',
   controller:'AreaCtrl',
   controllerAs: 'CTRL',
   views:{
      'main':{
          template: require('./app/area/_area.html')
      },
      'sidebar':{
          template: require('./app/area/_sidebar.html')
      }
   }

})

Nested views for UI-router docs

4 Comments

No, i don't have access to controller in views :(
How do you mean? :)
Simple, the actions form controller is not propagating, what i use it in main view it's working correctly...
@Lukas he is suggesting you to use a single Controller to all the Views. Witch is not correct.... but it could solve your problem
0

State is meant to be encapsulated by services, so in fact, if you have state that should be shared across the app, you should create a service.

Alternatively, you can have a controller in a higher scope, say you have a controller for the app, which can then be inherited by the sidebar and main page child scopes.

Comments

0

Maybe this answer is not the exact answer for your particular question. But from a architecture's view you should not use nested views to handle main view with sidebar.

Because this sidebar should be same for all states. So if you are using nested views you should specify your sidebar each time. Also you should write the code for sidebar in every states. That is not a recommended way to design your application.

I strongly recommend you to go through this Q&A.

Then how to design?

Make your sidebar as a simple template and use ng-include to render your footer part.

<footer ng-include="'/sidebar.html'" ng-controller="sidebarController"></footer>

As you can see there is a dedicated controller for your sidebar and you don't need to duplicate your code to each main controller.

2 Comments

Nope, sidebar will be different for different pages, so i need to have separated child views for it and main section.
@Lukas okay, if the case is like that then use nested views.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.