I have an issue in angular.js with directive/class ng-cloak or ng-show.
Chrome works fine, but Firefox is causing blink of elements with ng-cloak or ng-show.
IMHO it's caused by the converting ng-cloak/ng-show to style="display: none;", probably the Firefox javascript compiler is little bit slower, so the elements appears for a while and then hide?
Example:
<ul ng-show="foo != null" ng-cloak>..</ul>
Though the documentation doesn't mention it, it might not be enough to add the display: none; rule to your CSS. In cases where you are loading angular.js in the body or templates aren't compiled soon enough, use the ng-cloak directive and include the following in your CSS:
/*
Allow angular.js to be loaded in body, hiding cloaked elements until
templates compile. The !important is important given that there may be
other selectors that are more specific or come later and might alter display.
*/
[ng\:cloak], [ng-cloak], .ng-cloak {
display: none !important;
}
As mentioned in the comment, the !important is important. For example, if you have the following markup
<ul class="nav">
<li><a href="/foo" ng-cloak>{{bar}}</a></li>
</ul>
and you happen to be using bootstrap.css, the following selector is more specific for your ng-cloak'ed element
.nav > li > a {
display: block;
}
So if you include a rule with simply display: none;, Bootstrap's rule will take precedence and the display will be set to block, so you'll see the flicker before the template compiles.
As mentioned in the documentation, you should add a rule to your CSS to hide it based on the ng-cloak attribute:
[ng\:cloak], [ng-cloak], .ng-cloak {
display: none;
}
We use similar tricks on the "Built with Angular" site, which you can view the source of on Github: https://github.com/angular/builtwith.angularjs.org
Hope that helps!
Make sure AngularJS is included in the head of the HTML. See ngCloak doc:
For the best result, angular.js script must be loaded in the head
section of the html file; alternatively, the css rule (above) must be
included in the external stylesheet of the application.
I've never had much luck using ngCloak. I still get flickering despite everything mentioned above. The only surefire way to avoid flicking is to put your content in a template and include the template. In a SPA, the only HTML that will get evaluated before being compiled by Angular is your main index.html page.
Just take everything inside the body and stick it in a separate file and then:
<ng-include src="'views/indexMain.html'"></ng-include>
You should never get any flickering that way as Angular will compile the template before adding it to the DOM.
ngBind and ngBindTemplate are alternatives that do not require CSS:
<div ng-show="foo != null" ng-cloak>{{name}}</div> <!-- requires CSS -->
<div ng-show="foo != null" ng-bind="name"></div>
<div ng-show="foo != null" ng-bind-template="name = {{name}}"></div>
In addition to the accepted answer if you're using an alternative method of triggering ng-cloak...
You may also wish to add some additional specificities to your CSS/LESS:
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
.ng-cloak, .x-ng-cloak,
.ng-hide {
display: none !important;
}
I had a similar issue and found out that if you have a class that contains transitions, the element will blink. I tried to add ng-cloak without success, but by removing the transition the button stopped blinking.
I'm using ionic framework and the button-outline has this transition
.button-outline {
-webkit-transition: opacity .1s;
transition: opacity .1s;
}
Simply overwrite the class to remove the transition and the button will stop blinking.
Update
Again on ionic there is a flicker when using ng-show/ng-hide. Adding the following CSS resolves it:
.ng-hide-add,
.ng-hide-remove {
display: none !important;
}
Source: http://forum.ionicframework.com/t/beta-14-ng-hide-show/14270/9
I had a problem where a <div ng-show="expression"> would be initially visible for a fraction of a second, even though "expression" was initially false, before the ng-show directive got a chance to run.
The solution I used was to manually add the "ng-hide" class, as in <div ng-show="expression" ng-hide>, to make sure it started initially hidden. The ng-show directive will add/remove the ng-hide class as necessary after that.
Try to turn off the Firebug. I'm serious. This helps in my case.
Apply accepted answer and then make sure that Firebug in your Firefox is turned off: press F12 then turn off Firebug for this page - small button in upper right corner.
There's actually two separate problems that can cause the flicker issue and you could be facing either one or both of these.
Problem 1: ng-cloak is applied too late
This issue is solved as descibed in many of the answers on this page is to make sure AngularJS is loaded in the head. See ngCloak doc:
For the best result, angular.js script must be loaded in the head
section of the html file; alternatively, the css rule (above) must be
included in the external stylesheet of the application.
Problem 2: ng-cloak is removed too soon
This issue is most likely to occur when you have a lot of CSS on your page with rules cascading over one another and the deeper layers of CSS flash up before the top layer is applied.
The jQuery solutions in answers involving adding style="display:none" to your element do solve this issue so long as the style is removed late enough (in fact these solutions solve both problems). However, if you prefer not to add styles directly to your HTML you can achieve the same results using ng-show.
Starting with the example from the question:
<ul ng-show="foo != null" ng-cloak>..</ul>
Add an additional ng-show rule to your element:
<ul ng-show="isPageFullyLoaded && (foo != null)" ng-cloak>..</ul>
(You need to keep ng-cloak to avoid problem 1).
Then in your app.run set isPageFullyLoaded:
app.run(['$rootScope', function ($rootScope) {
$rootScope.$safeApply = function (fn) {
$rootScope.isPageFullyLoaded = true;
}
}]);
Be aware that depending on exactly what you're doing, app.run may or may not be the best place to set isPageFullyLoaded. The important thing is to make sure that isPageFullyLoaded gets set to true after whatever it is you don't want to flicker is ready to be revealed to the user.
It sounds like Problem 1 is the problem the OP is hitting, but others are finding that solution does not work or only partially works because they are hitting Problem 2 instead or as well.
Important Note: Be sure to apply solutions to both ng-cloak being applied too late AND removed to soon. Solving only one of these problems may not relieve the symptoms.
We ran into this problem at our company and solved it by adding "display: none" to the CSS styling for those flickering ng-show elements. We didn't have to use ng-cloak at all. Unlike others in this thread, we experienced this issue in Safari but not Firefox or Chrome -- possibly due to Safari's lazy repaint bug in iOS7.
For what it's worth, I had a similar issue ng-cloak not working. It may be worth checking your app/site with cache enabled to reuse source files to see if that helps.
With my run-in with flickering, I was testing with DevTools open and cache disabled. Leaving the panel closed with caching enabled fixed my issue.
Keeping the below statements in head tag fixed this issue
<style type="text/css">
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
</style>
official documentation
I couldn't get any of these methods to work, so I eventually did the following. For the element you want initially hidden:
<div <!--...--> style="display: none;" ng-style="style">
Then in your controller, add this at or near the top:
$scope.style = { display: 'block' };
This way, the element is initially hidden, and only shows when the controller code has actually run.
You can tune the placement to your needs, perhaps adding some logic. In my case, I switch to a login path if not currently logged in, and didn't want my interface flickering beforehand, so I set $scope.style after the logged-in check.
It's better to use ng-if instead of ng-show. ng-if completely removes and recreates the element in the DOM and helps to avoid ng-shows blinking.
I'm using ionic framework, adding css style might not work for certain circumstances, you can try using ng-if instead of ng-show / ng-hide
ref: https://books.google.com.my/books?id=-_5_CwAAQBAJ&pg=PA138&lpg=PA138&dq=ng-show+hide+flickering+in+ios&source=bl&ots=m2Turk8DFh&sig=8hNiWx26euGR2k_WeyaVzdixJ8k&hl=en&sa=X&redir_esc=y#v=onepage&q=ng-show%20hide%20flickering%20in%20ios&f=false
you'd better reference angular document, becuase the version[1.4.9] has update to below that make it could support data-ng-cloak directive.
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
I tried the ng-cloak solution above but it still has intermittent issues with Firefox.
The only workaround that worked for me is to delay the loading of the form until Angular is fully loaded.
I simply added ng-init in the app and use ng-if at the form side to check if the variable I set is already loaded.
<div ng-app="myApp" ng-init="loaded='yes'">
<form ng-if="loaded.length > 0">
<!--all my elements here-->
</form>
</div>
In addition to other answers, if you find the flash of template code to still be occuring it is likely you have your scripts at the bottom of the page and that means that the ng-cloak directive straight up will not work. You can either move your scripts to the head or create a CSS rule.
The docs say "For the best result, the angular.js script must be loaded in the head section of the html document; alternatively, the css rule above must be included in the external stylesheet of the application."
Now, it doesn't have to be an external stylesheet but just in a element in the head.
<style type="text/css">
.ng-cloak {
display: none !important;
}
</style>
source: https://docs.angularjs.org/api/ng/directive/ngCloak
I tried every solution posted here and still got flickering in Firefox.
If it helps anyone, I solved it by adding style="display: none;" to the main content div, then using jQuery (I was already using it on the page) $('#main-div-id').show(); once everything was loaded after getting data from the server;
I actually found the suggestion from Rick Strahl's Web Log fixed my issue perfectly (as I still had the odd issue with ng-cloak blinking raw {{code}} at times, especially while running Firebug):
The nuclear option: Hiding the Content manually
Using the explicit CSS is the best choice, so the following shouldn’t ever be necessary. But I’ll mention it here as it gives some insight how you can hide/show content manually on load for other frameworks or in your own markup based templates.
Before I figured out that I could explicitly embed the CSS style into the page, I had tried to figure out why ng-cloak wasn’t doing its job. After wasting an hour getting nowhere I finally decided to just manually hide and show the container. The idea is simple – initially hide the container, then show it once Angular has done its initial processing and removal of the template markup from the page.
You can manually hide the content and make it visible after Angular has gotten control. To do this I used:
<div id="mainContainer" class="mainContainer boxshadow"
ng-app="app" style="display:none">
Notice the display: none style that explicitly hides the element initially on the page.
Then once Angular has run its initialization and effectively processed the template markup on the page you can show the content. For Angular this ‘ready’ event is the app.run() function:
app.run( function ($rootScope, $location, cellService) {
$("#mainContainer").show();
…
});
This effectively removes the display:none style and the content displays. By the time app.run() fires the DOM is ready to displayed with filled data or at least empty data – Angular has gotten control.
I tried all of the answers above and nothing worked. Using ionic to develop a hybrid app and was trying to make an error message not flicker. I ended up solving my issue by adding an ng-hide class to my element. My div already has ng-show to show the element when there is an error. Adding ng-hide set the div to not display before angular is loaded. No ng-cloak or adding angular to the head necessary.
AS from the above discussion
[ng-cloak] {
display: none;
}
is the perfect way to solve the Problem.
I'm using ng-show in a directive to show and hide popups.
<div class="..." ng-show="showPopup">
None of the above worked for me, and using ng-if instead of ng-show would be an overkill. That would imply removing and adding the whole popup content into the DOM at every single click. Instead I added an ng-if into the same element to make sure it doesn't show at the document load:
<div class="..." ng-show="showPopup" ng-if="popupReady">
Afterwards I added the initialization into the controller responsible of this directive with a timeout:
$timeout(function () {
$scope.popupReady = true;
});
This way I eliminated the flickering issue and avoided the costly operation of DOM insertion at every single click. This came at an expense of using two scope variables for the same purpose instead of one, but so far this is definitely the best option.
Tried ng-cloak but still brief blinks. Below code rid them completely.
<body style="display:none;" ng-style="{'display':'block'}">
None of the solutions listed above worked for me. I then decided to look at the actual function and realised that when “$scope.watch ” was fired, it was putting a value in the name field which was not meant to be the case. So in the code I set and oldValue and newValue then
$scope.$watch('model.value', function(newValue, oldValue) {
if (newValue !== oldValue) {
validateValue(newValue);
}
});
Essentially when scope.watch is fired in this case, AngularJS monitors the changes to the name variable (model.value)
I would would wrap the <ul> with a <div ng-cloak>
I personally decided to use the ng-class attribute rather than the ng-show. I've had a lot more success going this route especially for pop-up windows that are always not shown by default.
What used to be <div class="options-modal" ng-show="showOptions"></div>
is now: <div class="options-modal" ng-class="{'show': isPrintModalShown}">
with the CSS for the options-modal class being display: none by default. The show class contains the display:block CSS.
Avoid line break
<meta http-equiv="Content-Security-Policy" content="
default-src 'FOO';
script-src 'FOO';
style-src 'FOO';
font-src 'FOO';">
Works with Firefox 45.0.1
<meta http-equiv="Content-Security-Policy" content=" default-src 'FOO'; script-src 'FOO'; style-src 'FOO'; font-src 'FOO';">
Related
When someone opens the page a <div> gets full width (1200px+). If I reload the page, the width is changed to the right one (550px). The browsers have their cache cleared, so this isn't a cache issue.
First visit:
After refresh:
This is a "custom HTML code" module in a Joomla 2.5 site. This is the code of divs that have their widths swapped:
<div class="art-nostyle">
<div class="custom">
<div id="script_nn_tabs54bfa417561de" class="script_nn_tabs" style="display:none;"></div>
<div id="nn_tabs_container_1____685___" class="nn_tabs_container outline_handles outline_content align_left nn_tabs_container_1_">
<div class="nn_tabs_nav" style="display: block;"></div>
At first sight I thought that the div id="nn_tabs_container_1____685___" was the problem, so I added this jQuery script at the end of the module :
var j = jQuery.noConflict();
j(document).ready(function () {
j("div[id^='nn_tabs_content_1____']" ).css("width","550px");
});
After it failed to fix it, I noticed that the problem was at the <div class="art-nostyle">. That div has no style at all! I can't use the above script for the art-nostyle div because it is added before every single module in the site. Could someone explain how it is possible when this probably isn't a cache issue - an element getting fixed width after a page refresh? I tried it on 5 different PCs that never visited the url before.
P.S. I can't recreate the problem in JSFiddle: that's why I didn't post a fiddle link.
Edit: Link of the site if someone want to check with his own eyes. Its the in middle of the index.
Edit2: I noticed that if i disable cookies the div wont change width after refresh. It will keep the full width.
If you're using jQuery, maybe you could remove the ".art-nostyle" class that may be inheriting weird styles from Joomla. You could give the one <div class="art-nostyle"> a unique ID (e.g. id="navigationLinks"), and then use this:
$(function() {
$("#navigationLinks").removeClass("art-nostyle");
$("#navigationLinks").css("width","550px");
});
You could also check to see if there's any other Javascript that references this div, because it seems weird that the problematic div would inherit the strange behavior just from HTML/CSS.
I had the same issue. However, I have found the answer. Use $(window).load() out instead of $(document).ready().
See also: window.onload vs $(document).ready()
I have a AngularJS application where I am loading data from a REST service.
Now what sometimes happens is that the brackets {{}} used to access values from scope are rendered and after that replaced by the real values. Now what I d like to do is add a ng-switch to the top DIV of the application and check whether a global var (e.g. pageLoaded (true|false)) is true or false. If its true, I d like to load the normal page, if its false, I d like to print something like "loading...". So my problem is how can I get notified (e.g. through a Angular Event) if all the data is ready, and is added to scope? Because after that I dlike to set pageLoaded to true.
Is there a way to do this in a generic way? I don't like to implement this per page.
Thanks a lot in advance.
Greets
Marc
You should use ng-cloak for that - http://docs.angularjs.org/api/ng.directive:ngCloak
For showing a loading panel, you can do something like:
<div ng-hide="true">Loading...</div>
So when angular finishes loading, ng-hide will occur and hide the loading panel.
Use ng-cloak to get rid of this sort of problems. And make sure you apply the ng-cloak directive to the body of the page so that this doesn't show up till the data is loaded properly. And use the following styling in your CSS file.
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none;
}
Note: you can even create some other element or div, thats something like a popup or notification bar, which shows "please wait till the data is comnpletely loaded". Set this div to display:none initially and in the Ajax call, change the display property to block/inline as needed and finally make it dispay:none after the success call back.. :)
One of the solutions is you can use ng-bind instead of using {{}} which will show ugly {{}} when the value is not rendered.
<div ng-bind="value">Loading ...</div>
For anyone who is having a problem more to do with the actual question than OP's specific scenario:
I had a fragment that was getting loaded-in after/by the main partial that came in via routing.
I needed to run a function after that subpartial loaded and I didn't want to write a new directive and figured out you could use a cheeky ngIf
Controller of parent partial:
$scope.subIsLoaded = function() { /*do stuff*/; return true; };
HTML of subpartial
<element ng-if="subIsLoaded()"><!-- more html --></element>
When a user enters the page I would like a div to be in the center with a heading, a quote underneath that is randomly picked from a list and a button to enter the site. This is all well and good but I cannot seem to get the button to fade in the main site and fade out the landing div. Here is a jsfiddle to try and help explain things more.
JSFIDDLE
As you will probably be able to tell, I'm not that great with JavaScript or jquery and what I have done so far is from learning bits and pieces and surfing the web through code examples
I do not see why it will not work as I had a play around in jsfiddle with a simplified version of what I want to do and it worked.
Simplified Version
Below code is simplified version (It wouldn't let me post without adding code?)
HTML
<div class="landingDiv">
<h1>LANDING DIV</h1>
<button id="showMain">Enter Site</button>
</div>
<div class="main">
<h1>Main Site</h1>
</div>
JQUERY
$("#showMain").click(function () {
$(".main").fadeIn(1000);
$(".landingDiv").fadeOut(1000);
});
CSS
.main {
display: none;
opactiy: 0;
}
Thanks in advanced.
Steve.
The first jQuery example threw an error:
$ is not defined
meaning jQuery is not defined/included. Which it wasn't. But in the second jsFiddle, you included jQuery.
You'll notice that on the left hand side of jsfiddle, you'll see that under the "Framewords & Extensions" heading that you can include a Framewordk - so, include jQuery!
Here is the updated fiddle with jQuery included: http://jsfiddle.net/6cGHF/1/
As you move forward in your JavaScript development, it is always a good idea to check your browsers developer tools for errors when something unexpected is happening. It always helps you, and when you ask questions on StackOverflow, providing these errors help us! :)
The shortcut for developer tools in Chrome is F12 - you can see a little red circle with an X in it if you have errors - click it for more info. But developer tools are also available in other major browsers (except IE8 and below).
Edit:
Wrap your click() event function in a $(document).ready()
$(document).ready(function() {
$("#showMain").click(function () {
$(".main").fadeIn(1000);
$(".landingDiv").fadeOut(1000);
});
});
What was happening was that your HTML file is read from top to bottom. So it would have reached your click function before the #showMain element had been read. So, jQuery couldn't find it.
The reason this wasn't a problem in jsFiddle was because all the JavaScript code was wrapped in an "onLoad" function (which is, admittedly, a little different to $(document).ready()) but it solved this problem for you by executing your JavaScript after everything had already been loaded. You can see that on the left hand side in the fiddle I linked above, you'll find a dropdown with "onLoad" selected. In it, you can also choose "OnDomready" (which would be equivalent to $(document).ready())
In summary:
DON'T use $(document).ready() in jsFiddle. You don't need it.
DO use $(document).ready() around javascript that relies on the fact that the DOM is ready (ie. "all of your content is visible to your JavaScript").
The problem in your fiddle is you have not added jQuery so when you try and reference it with '$', a javascript error is thrown. Simply add in the reference to a jQuery library and your fiddle works to fade out the button when clicked.
Your problems:
1) Add jQuery library to your fiddle.
2) Remove opacity:0; from .main in your CSS. The display:none; is sufficient.
3) Use this to fade out/in the elements:
$("#showMain").click(function () {
$(".landingDiv").fadeOut(1000, function () {
$(".main").fadeIn(1000);
})
});
I'm getting a bit confused with my work.
My Problem is, I want to change a Element that's covered with an Element.
the HTML-structure:
<ul class="calendar-content">
<li>
<a href="#day02" onClick="popup('02');">
<span class="day"><strong>02</strong></span>
<span class="content" id="content">
<small>02</small>
<strong>Inhalt Tag 01</strong>
</span>
</a>
</li>
The user is only seeing the first span(class=day). After a click on the link the
second span(class=content) should "appear".
My first idea was:
.calender-content .a:visited .content{
display:block;
}
Or this one:
//.calender .content got margin-left:120px and is out of view
.calender-content .a:visited .content{
margin-left:0px;
}
But nothing happens. Maybe it isn't valid but I saw stuff like this before.
I just want to display the second span after the link is visited.
Either setting the display style to block or changing the margin to 0 and animate that with
-transition.
But nothing the styles doesn't appear on the span element.
If there's a way arround in CSS, that would be great. So I don't have to use JS.
Cheers Dan
Should be:
.calendar-content a:visited .content { display: block; }
You have ".a", which means "elements with class 'a'", not "elements with tag name 'a'" :-)
Now the thing is, I'm not sure that ":visited" will be "true" (or whatever the appropriate term would be) if your <a> tag isn't really something that "visits" another URL. If that's the case, then your event handler can add a class to the anchor. If your event handler does allow the anchor to move to the label, then I think it should work.
Your first problem is the . notation that means "class" and not "tag". See #Pointy's answer for details and fix.
But then, you shouldn't rely on :visited. Indeed, it can be used for history sniffing, and browsers will probably end up removing support for most CSS properties that change layout (such as display), just like Firefox already does.
A pure CSS solution would be to use the :target pseudo-class. However, it is not supported in IE ≤ 8. If it is a requirement, you should go to JS.
Any way you choose, you should refactor your markup. The link should not contain something it toggles. <small> is a good example of an awful markup-as-presentation use. Use a classed span.
Is it OK to write Javascript code to solve a browsers compatibility problem or I should never need that and everything should be solved using CSS only?
My problem:
I have a menu in an ASP.Net application, this menu renders a hidden image control supposing that height=0 and width=0 will not render anything. That's true in IE but it keeps an empty area in Chrome and it looks ugly.
This is the generated code:
<img alt="Skip Navigation Links" src="/WebResource.axd?d=6z..."
width="0" height="0" style="border-width:0px;" />
I wrote the following code to solve the problem:
<script type="text/javascript">
$('img[height="0"]').css('display', 'none');
</script>
Is what I did true and the only way to solve such problems?
Note: The code in my example is generated for an ASP.Net menu control and I have no access on it to set a specific style
I don't think javascript is nessessary in this case as you can either add a class or id to the element and set a style or use:
img[height="0"] {
display: none;
}
You are using javascript to change a CSS style property.
Why not simply use it like this: style="border-width:0px; display:none;" ?
[Edit]
If you really have no access to how the code is generated, you might try adding a style for the specific img element withing your menu div: .parentClass img { display:none; }.
It's a bit strange if there is no possibility to define css classes for any of these elements.