Angular ng-include strange behavior - causing URL address change - angularjs

I've noticed a strange behavior of ng-include -- it is causing a strange side effect on the browser in some cases.
Here is a page, that contains a simple twitter bootstrap tab pane
<body>
<ul class="nav nav-tabs">
<li class="active">Tab 1</li>
<li>Tab 2</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab1">AAA</div>
<div class="tab-pane" id="tab2">BBB</div>
</div>
</body>
Now, if I add ng-include anywhere in the page, for example at the beginning of the page:
<body>
<ng-include src="'page1.html'"></ng-include>
...
It doesn't matter what the included file contains, it can be even empty, but this will cause each click when switching tabs to add #/tab1, #/tab2, etc. to the page URL. This happens in all browsers, which is undesirable. On Chrome, this also causes the tab icon to flicker, and for a moment it shows default white icon before it reloads the page specific icon.
Anyone experienced something similar? Why adding ng-include would cause this?
I also tried doing the include without angular (by using jQuery.load()) and there is no issue seen.
This can be fully experienced on a standalone page, but on this plnkr page I created, although one cannot see the URL, and the flicker effect in Chrome is less visible, but still the effect can be seen in Chrome.

The url changing behavior come from the $location service, which is used by ng-include. So you could be able to reproduce it by just injecting the $location service somewhere in your app.
See the What does it do? section of this $location guide, and the action that causing the problem is:
Maintains synchronization between itself and the browser's URL when the user clicks on a link in the page
This answer your question "Why adding ng-include would cause this?".
To prevent the url from changing by the $location service, you could do it like this:
appModule.run(function ($rootScope) {
$rootScope.$on('$locationChangeStart', function ($event, newUrl, oldUrl) {
// may add some logic here to prevent url changes only that come from clicking tab.
$event.preventDefault();
});
})
Example plunker: http://plnkr.co/edit/4289uwL1mHSRj6oP4dl1?p=preview
Hope this helps.

Related

Controller Scope Array not load updated data on another controller

i created one index page which have "NavigationController" and bind the menu on index page. when i redirect to new page controller and inject it "NavigationController" to bind latest menu on next page but it always display old menu. when i refresh the page then it loads nice with new menu.
<nav class="static-sidebar" role="navigation">
<ul ng-controller="NavigationController" id="sidebar" ng-init="!layoutLoading">
<li ng-repeat="item in menu" ng-include="'templates/nav_renderer.html'" ng-show="{{item.hasRights}}" ng-cloak></li>
</ul>
And Controller with my factory method which return meun is :
$scope.menu = GetHttpRequest.GetMenu();
Now, I Add into Another page i.e
<div ng-controller="NavigationController"></div>
but this not load latest menu untill i refresh the page
so , can you help me in this?
{{}} not needed in ng-show.
Use ng-show="item.hasRights" instead of ng-show="{{item.hasRights}}"
If it works after refreshing it means that it is something with loading order in your site. Check if you have correct order of loading, like: vendor lbirariers -> your libraries -> (...) -> your controller
also check your dependency injection headers in js files, cause you might skipped something

Detecting page scroll/ current section being viewed in AngularJs

My page is divided into sections : #page-1 and #page-2
See Plnkr: http://plnkr.co/edit/RZJLmsWDfs63dC0QuDJi
<body>
<section id="page-1">
This is page 1. It takes the whole height of the browser. User has to scroll down to see page-2.
</section>
<section id="page-2">
<span class="animated bounce">This is page 2 </span>
</section>
</body>
Animation classes are being applied to different elements in #page-2.
However by the time the user scrolls down to these elements, the animation has already finished. Hence they just look like static objects.
Is there anyway I can detect when #page-2 is currently being viewed and then call a function to addClass('animated bounce') to certain elements ?
I would like to achieve this in angularjs if possible
I have found a angularjs directive that is probably helpfull for you in this case. Inview tries to solve this exact problem by reporting to you if a dom element is visible on the screen. Unfortunately I have been unable to test my solution because I couldn't find a minified js file of Inview but I assembled some code that should work:
<section id="page-2" in-view="{$inview ? isFocused=true;}">
<div ng-class="{'animated bounce': isFocused}">This is page 2 </div>
</section>
The $inview is supposed to be true whenever the element is in visible in the browser. This leads to the scope variable isFocused being set to true and therefor the animation class is added to your div.
This should work as you have intended in your question, if it does not work for some reason please let me know so I can improve my answer.

Possible bug in with angular-ui-bootstrap and angular-ui-router (tabset inside nested ui-view)

I'm looking for confirmation or possibly a workaround, this is not intended as a bug report.
TL;DR I think I found a bug, not sure which thing it's in. I've got this html:
<div ui-view>
<ul>
<li><a ui-sref="page">Default</a></li>
<li><a ui-sref=".nestedView">Test</a></li>
</ul>
<div ui-view>
<tabset>
<tab>
<tab-heading>Example</tab-heading>
Tab content, blah blah blah
</tab>
</tabset>
</div>
</div>
and I get this error:
Error: [$compile:ctreq] http://errors.angularjs.org/1.3.0/$compile/ctreq?p0=tabset&p1=tab
happens with angular 1.3.0+ but not 1.2.9
Plunker
Details:
I think I've found a bug with the combination of angular 1.3.0+, angular-ui-router, and angular-ui-bootstrap.
I've got a nested ui-view where the default contains a <tabset> from angular-ui-bootstrap. When I navigate away from the default view I get this error:
Error: [$compile:ctreq] http://errors.angularjs.org/1.3.0/$compile/ctreq?p0=tabset&p1=tab
I've narrowed this down as happening in 1.3.0+ (even the beta 1.4.0) but not in 1.2.9.
Here's the plunker: http://plnkr.co/edit/E0laKNSJGp31q1swQ2jp?p=preview
That's set for version 1.3.0 and shows the error in the console when you switch from the Uno > Tabs view to the Uno > No Tabs view. If you set it to 1.2.9 you'll see it goes away.
This does not appear to impact functionality but it sure is irritating to see that error all the time. For now I'm just going to downgrade my angular version.
SIDE NOTE: I'm really not sure where to submit this bug. My first thought would be to angular-ui-bootstrap, but I'm not certain. If anyone is involved in these projects please direct me. Otherwise I'll just put it in both the angular-ui-router and angular-ui-bootstrap github issues.

ng-view doesn't evaluate bootstrap javascript (css and so on)

My problem is, when Angular load templateUrl (through $routeProvider) inside ng-view it doesn't evaluate all javascript as well. I tried to figure it out, but now i'm really confused. During my search i found a lots of new topic, and i've lost in them. Any idea?
Tale
I tried to figure it out if anybody else met this problem before, or if there are any solution for this problem. The way i've found was something like "lazy-loading" directives or using requirejs, but i'm not sure if those tools are really solves this problems.
As Buu Nguyen mentioned in this thread
That's the way jqLite works. If you want scripts in templates to be
evaluated, include jQuery before AngularJS. If jQuery is included, the
script will be evaluated. Try removing jQuery, and you see the
originally observed behavior.
I've tried, including jquery before angularjs but doesn't cause any effect at all.
There are sevaral threads i read, for example
stack-overflow-19434249
stack-overflow-12197880
stack-overflow-21994037
but nothing lead to solution (maybe i've missed a thing). And i think, this is not even my problem. I don't want to (re)load javascript files, i just want to force evaluate my bootstrap.
Honestly i'm really confused now.
Afterward first time i met RequireJS. (lazy loading, and friends, again)
I've watched Thomas Burleson's video on youtube and i nearly understand what is it. And i looked much more articles in topic (because i found it's interest) but solution should be somewhere else.
Here is the situation
While i'm working on my angularjs app, i've made a partial site as separated .html file (just in case) and it seems pretty. Then i cut this .html file to pieces (header, top-menu, content, footer) and use its body tag as div inside a partial urlTemplate.
<body ng-app="myApp" id="page-top">
<div class="wrapper">
<div class="navigation">
<div top-menu></div>
</div>
<div ng-view></div>
<footer id="page-footer">
<div class="container">
<span>Copyright © 2014. All Rights Reserved.</span>
<span class="pull-right">Go to top</span>
</div>
</footer>
</div>
</body>
angular $routeprovider:
angular.module('myApp').config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'main/templates/main.html'
}).when('/ad-element', {
templateUrl: 'submit/templates/submit.html'
}).when('/404', {
templateUrl: 'errors/templates/404.html'
}).otherwise({
redirectTo: '/404'
});
}]);
submit.html
<div class="page-sub-page page-submit">
<div ng-controller="SubmitController" class="container">
<form ...></form>
</div>
</div>
Every angular function is working, the only visible difference is the appearance.
This is the good one:
And this is the bad one:

Remove nav menu from login page

Have base html admin_layout.html where i wrote this:
<body>
<div ng-include="'/static/partials/admin_navigation.html'"></div>
<div ng-view></div>
Interested to know how may remove admin navigation from login page?
Tryed to set variable hide_menu in LoginCtrl and hide it with ng-if="hide_menu", but this doesn`t work for me. It hide menu in all admin panel.
UPD: Fixed it adding to navigation div Menu controller. Or better create menu directive?
UPD2:
Added in admin_app.js:
adminApp.run(function($rootScope, $location) {
$rootScope.location = $location;
});
and in admin_layout.html:
<nav ng-include="'/static/partials/admin_navigation.html'" ng-if="location.path() !== '/admin/login'"></nav>
Now everything work fine
Fixed problem using code that i wrote in UPD2 of my question
As far as i understand it right now, your Problem is that the value of "hide_menu" does not depend on the route you're currently in.
So i would suggest you set the value in the controller according to the page you are currently displaying. You could for example listen for the $routeChangeSuccess event and read out the $route.current object accordingly.
If you need more specific help, please provide a plunkr!
yes you can work it with ng-show or ng-hide.
like for those URL's you dont want to have the nav bar you can hide iot using ng-hide i.e.
URL for which you wants to hide nav bar -http://**.com/view1.html
<div ng-include="'/static/partials/admin_navigation.html'" ng-hide="URL == '/view1.html'"></div>

Resources