Kraken
Kraken

Reputation: 5870

dynamic header/menu in angularjs

While transitioning an existing angular site, I encountered an annoying problem. The initial symptom was that a certain controller was not running it's initialize function immediately following the login. I logged and I tracked, and eventually I realized it was a design flaw of the page. Essentially, index.html contains a <header>, <ng-view>, and <footer>. There are a couple of ng-if attributes that live in the header that I want to evaluate after the login, but since the view is the only thing that is reloaded, it was not reinitializing the header controller, and thus not updating the ng-if values.

Then I was reminded of ngInclude, which seems like the perfect solution, until I got it hooked up and realize that doesn't work either. It loads the template the first time, and doesn't reinitialize when the view changes. So then I got the bright idea of passing the HeaderController to another controller or service, and controlling this one stubborn boolean value through a proxy of sorts. That also didn't work. Then I tried putting a function and a boolean into another service, and mirroring that property in the header controller, but thus far I have not gotten this working.

I have done plenty of research about multiple views in the index, and so far I hear a lot about this ui-router, but I'm still not convinced that is the way I want to go. It does not seem to be a simple solution. I have not tried putting the ng-include into the templates yet either, because then I feel like that is going back in time to when we had to update 100 pages every time we changed the menu.

I lost a whole day to this. If anyone could tell me how to trigger the evaluation of this one property in my header controller which I would like to live outside the other templates, please let me know!

Upvotes: 0

Views: 730

Answers (1)

Bolza
Bolza

Reputation: 1944

Ok so you need to know in your HeaderController when the view has reloaded. There's a number of ways of doing this but the easier and maybe the more correct in this particular case is with an event.

So when you are refreshing the view you just do this, let's say you need the new value of ob1 and ob2 variables.

// ViewController
$rootScope.$emit('viewRefresh', {ob1: 'newvalue1', ob2: 'newvalue2'});

And in your HeaderController you need to listen for that event, and set on your $scope the new values for those attrs (if you're not using controller as syntax).

// HeaderController
$rootScope.$on('viewRefresh', function onRefresh(event, data) {
    $scope.ob1 = data.ob1;
    $scope.ob2 = data.ob2;
})

Another Solution Sharing a Promise through a Service (using $q)

function HeaderService($q) {
    var defer = $q.defer();
    return {
        getPromise: function() {return defer.promise},
        notify: function(data) {defer.notify(data)}
    }
}

function HeaderController(HeaderService) {
    var vm = this;
    HeaderService.getPromise().then(function(data) {
        vm.ob1 = data.ob1;
        vm.ob2 = data.ob2;
    })
}


function ViewController(HeaderService) {
    var data =  {ob1: 'newvalue1', ob2: 'newvalue2'};
    HeaderService.notify(data)
}

Upvotes: 1

Related Questions