5

I have a search bar in my index.html template that I need to hide on some pages. I am using ui-router and $state.

The only way I can make this work is to inject $rootscope into all my controllers to either ng-hide: true or false to turn them on or off where needed. (I only really need to hide on 1 or 2 pages)

I don't think this is the correct way to do it as all my controllers are now dependent and injected on the $rootscope.

Is there another way to do this?

cleftheris
  • 4,626
  • 38
  • 55
ottz0
  • 2,595
  • 7
  • 25
  • 45

6 Answers6

3

Let's start with a global controller example GlobalCtrl which is added to the body or html tag like ng-controller="GlobalCtrl.

Doing this will enable us to keep the scope of this GlobalCtrl throughout your single page Angular app (as you are using ui-router) and we can avoid the usage of $rootScope (actually mimicking the usage of $rootScope).

Now, inside your GlobalCtrl define something like this:

// Using an object to avoid the scope inheritance problem of Angular
// https://github.com/angular/angular.js/wiki/Understanding-Scopes
$scope.globalData = {showSearchBar: true};

// This callback will be called everytime you change a page using ui-router state
$scope.$on('$stateChangeStart', function(event, toState, toParams) {
    $scope.globalData.showSearchBar = true;

    // Just check for your page where you do not want to display the search bar
    // I'm using just an example like I don't want to display in contac-us page named state
    if (toState.name == 'contact-us' || toParams.foo == "bar") {
        $scope.globalData.showSearchBar = false;
    }
});

Now, in your index.html, just use ng-show:

<div ng-show="globalData.showSearchBar">
    <input type="text" ng-model="query" />
</div>
Shashank Agrawal
  • 25,161
  • 11
  • 89
  • 121
1

You can access $rootScope from your template using $root in expression. Like:

<div ng-show="$root.appSettings.flag">
    <span>Hello!</span>
</div>
xSaber
  • 384
  • 1
  • 11
  • How do I turn this on or off from the controller? Do I still need to inject $rootscope into my controllers? – ottz0 Dec 11 '15 at 00:54
  • @ottz0 No, you don't need to inject rootScope as dependency, simply use it in template. – xSaber Dec 11 '15 at 12:39
0

For example

<div ng-controller="SearchCtrl">
<div ng-if="show">
...
</div>
</div>

app.controller('SearchCtrl', ['$state', '$scope', function($state, $scope) {
    $scope.show = !$state.is('someState1') && !$state.is('someState2');
}

This is not that good style, but will simply works.

Petr Averyanov
  • 9,327
  • 3
  • 20
  • 38
0

I don't like going on with a controller, I think that it's better to separate each part of your application in a way that is not dependent of another controller.

I will use a service to share the data:

'use strict';

angular.module('yourModule')
    /**
        A service used to share resources between controllers
    */
    .factory('Shared', [function () {
        var resources = {};

        resources.targetList = [];
        resources.isVisibleDivA = true;
        resources.isVisibleDivB = false;

        return resources;
    }]);

In this way, injecting the service you will always be able to interact with the status variables needed to format correctly your layout.

If you want to reuse a controller you simply have to add a mocked service and you wont need to depend on a controller.

Gianmarco
  • 2,536
  • 25
  • 57
  • How do you access this in the controller – ottz0 Dec 15 '15 at 10:27
  • Isn't this just injected into the local scope. The same as putting into each controller anyway? – ottz0 Dec 15 '15 at 10:48
  • a service is a Singleton, so wherever you use it you will always have the same instance – Gianmarco Dec 15 '15 at 11:01
  • How can I turn this on or off where I need it? Can you show me the usage? – ottz0 Dec 15 '15 at 11:17
  • I can't understand too well what's the problem – Gianmarco Dec 15 '15 at 11:31
  • I have an Item in my index page ng-show='search" it's loaded in the root scope, when it gets to the hotels page I want to hide it – ottz0 Dec 15 '15 at 11:42
  • you should move that "search" used in ng-show in the service, is that the point – Gianmarco Dec 15 '15 at 11:44
  • The condition that is set in the $rootscope is either true or false though. I cant see from what you have provided how I can use it.
    – ottz0 Dec 15 '15 at 11:49
  • Ok...I got you pull the condition out of $rootscope and use the service to set the condition of true or false – ottz0 Dec 15 '15 at 12:01
  • precisely, in that way you are not polluting the rootscope and you can inject that variable where you need – Gianmarco Dec 15 '15 at 12:07
  • Just one thing though..just by using ng-show on my index page sets the condition and by doing show puts it on the $rootscope..would it be better to add or hide a class? – ottz0 Dec 15 '15 at 12:18
0

In ui-router you can use abstract states to create hierarchies. This way you can have a parent route witch has the searchbar view and another that does not. All your actual routes can inherit from these two and you are done.

Something like this

$stateProvider
.state('rootLayout', {
    abstract: true,
    // Note: abstract still needs a ui-view for its children to populate.
    // You can simply add it inline here.
    template: '<div><div ui-view="topbar"></div><div ui-view></div></div>'
})
.state('searchbarLayout', {
    abstract: true,
    views: {
        '@rootLayout': { 
             // Note: abstract still needs a ui-view for its children to populate.
             // You can simply add it inline here.
             template: '<div ui-view></div>'
        },
        'topbar@rootLayout': { 
             template: '<input type="search" />'
        },
    }    
});
cleftheris
  • 4,626
  • 38
  • 55
0

I registered the object in the run function of the app

.run([ '$rootScope', function ($rootScope) {
  $rootScope.searchBar = { value: true };
}])

Then used the scope to change the value. This stops adding $rootscope into every controller

$scope.searchBar.value = false;

Set the value in the index.html page

<div ng-show="searchBar.value" ng-include src="'app/shared/search.html'"></div>
ottz0
  • 2,595
  • 7
  • 25
  • 45