Reloading an angular view?

448 views
Skip to first unread message

Zach Schneider

unread,
Feb 11, 2014, 7:04:13 PM2/11/14
to ang...@googlegroups.com
I have an angular application that i'm trying to use impress.js inside of. 

I've been able to overcome the issue with url hash conflicts, the only issue I have is with initiating the impress.js. 

The impress page is a link at the top of the navigation. I want to be able to move from that page to another page and back without issue. However, the way impress.js works you can only run impress().init() one time, so once I click away from the impress page and navigate back to it impress.js stops working. 

I've solved this issue with the following code:

if(!angular.isDefined($rootScope.loadCount)){
$rootScope.loadCount = 0;
}else{
$rootScope.loadCount++;
}
if($rootScope.loadCount == 1){
         $window.location.reload()
}

But I feel like there should be an easier way to do this. Is there a way to have visiting a page a second time re-render the view like you have not been to the page yet?

Luke Kende

unread,
Feb 12, 2014, 1:17:22 AM2/12/14
to ang...@googlegroups.com
I don't have enough information to adequately answer your question, but my best guess is that you are new to angular?

Are you using routeProvider for your views?  If so the views reload the associated controller, so could not your call impress.init() be there?  

Can you create a plunker or similar to demonstrate?

Zach Schneider

unread,
Feb 12, 2014, 11:15:26 AM2/12/14
to ang...@googlegroups.com
Yep, I've only spent a few days on Angular and i'm working on modifying code someone else wrote. 

The code is written on a platform that required a lot of hacking to get to work, so i'm not sure how i'd even start making a plunker from it.  I can show you my controller and the route provider though:

Routeprovider:
ngModMain.config(['$routeProvider',
    function($routeProvider, $rootScope, $scope) {     
  $routeProvider
            .when('/home', {
                templateUrl: 'demoDashboard.html',
                controller: 'demoDashboardCtrl'
            })

        .when('/home/wall', {
            templateUrl: 'demoDashboard.html',
            controller: 'demoDashboardCtrl'
        })
            .when('/home/default', {
                redirectTo: '/home'
            })


            //This is the one i want to have refresh as if the template had never been rendered before
            .when('/expo', {
                templateUrl: 'expo.html',
                controller: 'atcExpoCtrl'



           .otherwise({
                redirectTo: '/home'
            });

    }
]);


Controller:

var ATCExpo = angular.module('ATCExpo', [])


//This directive broadcasts when the last ng-repeat is run for building out the impress.js slides. 
.directive('initiateImpress', function($timeout, $rootScope){return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit('ngRepeatFinished');
});
}
}
};
});

ATCExpo.controller('atcExpoCtrl', function($scope, $timeout, $route, $rootScope, $location, $window){

        //This is the logic i'm currently using to refresh the page. I feel there should be a way to do this by refreshing the template/controller and not the entire window.
if(!angular.isDefined($rootScope.loadCount)){
$rootScope.loadCount = 0;
}else{
$rootScope.loadCount++;
}
if($rootScope.loadCount == 1){
$location.refresh();
             
               // this failed to work.
               //$route.reload();
}
//Event Listener for ng-repeat on Demo impress cards.This is needed because impress tries to render the cards while ng-repeat is still populating the attributes in the template.
$scope.$on('ngRepeatFinished', function() {
//if($scope.loadCount ===0){
    impress().init();
//}
});
});


Template:

// the demo value here is from another script, it currently works without issue.
<div id="impress" class="impress-not-supported" name="impress">
    <div ng-repeat="demo in demos" class="step top stepCSS" data-x="{{(($index + 1) * 1000) + 1000}}" data-y="{{(($index + 1) * -1500) - 1500}}" data-z="{{(($index + 1) * 2000) + 2000}}" data-rotate="180" data-scale="3" initiate-impress="">
        <h1>{{demo.name}}</h1>
        <div class="number">
            <img src="{{demo.logo}}" />
        </div>
    </div>

Luke Kende

unread,
Feb 12, 2014, 11:59:56 AM2/12/14
to ang...@googlegroups.com
So, the main thing I can see here is that the DOM to which you are applying impress to gets removed completely on a view change, so impress's references would be void after leaving the view and returning.

What about putting <script> reference to impress sources in the view template itself instead of the <head> of the page?  That way it gets removed and loaded each time the view changes along with the template. Then instead of emitting an event, just call impress.init() within the directive's linking function?  (impress.init() can be called in the directive just as easily as in the controller since it's on the global window object)

Obviously, you'd have to test it out to see if it's feasible, but offering alternatives for you to consider. 


--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/I1tTfbTg33s/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/groups/opt_out.

Zach Schneider

unread,
Feb 12, 2014, 12:37:51 PM2/12/14
to ang...@googlegroups.com
I tried that first actually. The problem is impress writes everything to a canvas tag and loads each class as a child value. Once you leave the view and return angular still has the rendered impress elements inside the DOM, so impress throws out an error since the child values already exist. So even when i'm completely reloading the view and having the impress reference inside the view it still throws out an error. That lead me to believe that angular isn't actually removing the DOM manipulation Impress does after intial render when reloading a controller/view. 

window.location.refresh() does fix this, but that reloads the entire application and not just the view i'm trying to re-render. My hope is that angular has something like $setPristine() that can be used for DOM elements instead of forms.

Luke Kende

unread,
Feb 12, 2014, 12:58:40 PM2/12/14
to ang...@googlegroups.com
Basically, impress needs to offer a way to init, cleanup, re-init, or hide/show.  That can be done in the directive if impress exposes some methods to handle special cases.

Otherwise, you might need to remove the view from routeProvider and just use ng-show /ng-hide in the index.html (main template) when that link is clicked which doesn't remove the DOM only sets display:none.  That way the directive inits impress once and the click just hides or shows it... just be sure the html housing the impress DOM is not removed by a view change.

//index.html
<a ng-click="showImpress=true">Impress Link</a>

<div ng-show="showImpress">

 <div id="impress" class="impress-not-supported" name="impress">
    <div ng-repeat="demo in demos" class="step top stepCSS" data-x="{{(($index + 1) * 1000) + 1000}}" data-y="{{(($index + 1) * -1500) - 1500}}" data-z="{{(($index + 1) * 2000) + 2000}}" data-rotate="180" data-scale="3" initiate-impress="">
        <h1>{{demo.name}}</h1>
        <div class="number">
            <img src="{{demo.logo}}" />
        </div>
    </div>

</div>

<div ng-hide="showImpress">
  //route views
  <div ng-view></div>
</div>

If you still need the url in the address to reflect the change, there are ways to get it done.  

Zach Schneider

unread,
Feb 12, 2014, 1:02:42 PM2/12/14
to ang...@googlegroups.com
Thanks Luke! i'll look into that. I really appreciate the help.
Reply all
Reply to author
Forward
0 new messages