I'm attempting to conditionally show/hide two divs using ng-show with a boolean value in $scope, based on when an AJAX call has completed. Basically, with the following layout:
<div id="div1" ng-show="!loadingData">
<!--Some markup here-->
</div>
<div id="loadingMessage" ng-show="loadingData">
Loading...
</div>
The function provoking the change contains the following:
$scope.loadingData=true;
var promise = dao.doAjaxGet("url");
promise.then(function(data){
//Hide loading message
$scope.loadingData=false;
});
The AJAX call is operating correctly, and this works fine in Chrome, Safari, Firefox, but not the two versions of IE that we are required to support - IE7 and IE8. The loading message stays hidden and div1 stays visible regardless of what status the call is in. Can anyone advise on this?
If you have console.log in your controller, get rid of it. It helped to get things working in IE8 e.g. ng-hide
Turns out this is caching related. Chrome and IE both cache ajax calls after the first call. I've managed to resolve the problem in chrome by introducing cache:false into the ajax call configuration but this seems to have no effect in IE. If anybody has further information on this, please let me know.
Here's a fully working Angular ie7 template. Ues a very old Angular, but works
My HTML File
https://cdn.jsdelivr.net/bootstrap/3.3.6/css/bootstrap.min.css'>
<!--[if lte IE 8]>
<script type="text/javascript">
// IE7 fix for missing
if (!window.console) {
var console = {
log: function() {},
warn: function() {},
error: function() {},
time: function() {},
timeEnd: function() {}
}
}
</script>
<script src="https://cdn.jsdelivr.net/json2/0.2/json2.js"></script>
<![endif]-->
<!--[if lte IE 9]>
<script type="text/javascript" src="https://cdn.jsdelivr.net/es5.shim/4.5.7/es5-shim.js"></script>
<![endif]-->
<script type="text/javascript" src="https://cdn.jsdelivr.net/html5shiv/3.7.3/html5shiv.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/angularjs/1.1.5/angular.js"></script>
<script>
/**
* Main AngularJS Web Application
*/
var app = angular.module('myapp', []);
app.controller('MyPageCtrl', pageController);
function pageController($scope) {
$scope.languages = [
{ 'Id': 1, 'Name': 'French' },
{ 'Id': 1, 'Name': 'German' },
];
};
</script>
</head>
<body ng-controller="MyPageCtrl">
<div class="col-xs-12">
<select name="languagesDropDown" id="languagesDropDown" class="form-control" style="width: 200px;">
<option ng-repeat="language in languages" value="{{language.Id}}">{{language.Name}}</option>
</select>
</div>
I faced this same issue of ng-show not working in Internet Explorer.
The official ngShow AngularJS documentation mentions about this, and provides a few workarounds for this.
(I'll copy-paste the text mentioned in that link, in case that link has expired or is not working for some reason)
When using ngShow and / or ngHide to toggle between elements, it
can happen that both the element to show and the element to hide are
visible for a very short time.
This usually happens when the ngAnimate module is included, but no
actual animations are defined for ngShow / ngHide. Internet
Explorer is affected more often than other browsers.
There are several way to mitigate this problem:
Disable animations on the affected elements.
Use ngIf or ngSwitch instead of ngShow / ngHide.
Use the special CSS selector ng-hide.ng-hide-animate to set {display: none} or similar on the affected elements.
Use ng-class="{'ng-hide': expression} instead of instead of ngShow / ngHide.
Define an animation on the affected elements.
The second suggestion (replacing ng-show with ng-if) worked for me. So in your case, you could consider using this -
<div id="div1" ng-if="!loadingData">
<!--Some markup here-->
</div>
<div id="loadingMessage" ng-if="loadingData">
Loading...
</div>
Related
I'm just curious why this happens, and if it can be fixed (I'm aware IE is old & evil, not to be used online any more, this is just for some test-case and compatibility).
There is listener for "beforeunload" and changes body class (I see it does add that class), but it does not apply the style defined for that class in IE (other new browsers work fine).
<?php /* emulate long load */ sleep(2); ?><!DOCTYPE html>
<html><head><meta charset="utf-8">
<style>
body.is-unloading {background:#333;opacity:0.5}
</style>
<script>
function xx(){ document.querySelector('body').className += ' is-unloading'; }
window.addEventListener("beforeunload", function(event) { xx(); });
</script>
</head><body class="not-unloading">
<button onClick="window.location.reload()">RELOAD</button>
</body></html>
I'm using the Polymer/web-component-tester to run automated tests of my components.
I've run into an issue where a component test will pass if run in isolation, but fail when run using a file glob - for example:
FAILS: wct components/**/test
SUCCEEDS: wct components/btn-component/test
After a fair bit of digging, I found the reason is the change in browser behaviour: in both cases the launched browser has two iFrames side-by-side, with the right one showing the test progress, and the left showing the component. The globbed test run results in a significantly narrower left (component) iFrame.
When using polymer-gestures to simulate mouse clicks, the narrower iFrame causes issues because it can often render a horizontal scrollbar and change a component's clickability.
The following is an example of a component & test that fails as described. It renders a Cancel button a few hundred pixels to the right.
Component
<link rel="import" href="../../bower_components/polymer/polymer.html">
<polymer-element name="btn-component" attributes="name">
<template>
<style>
:host {
display: block;
width: 400px;
}
</style>
<div layout horizontal>
<span flex></span>
<div id="cancel_button" on-tap="{{cancel}}">Cancel</div>
</div>
</template>
<script>
Polymer({
ready: function() {
console.log("btn-component component ready!");
},
cancel: function(event, detail, sender) {
console.log("Cancel Btn!", event, detail, sender);
this.fire('cancel_btn', {});
}
});
</script>
</polymer-element>
Test
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>btn-component Tests</title>
<script src="../../../bower_components/webcomponentsjs/webcomponents.js"></script>
<script src="../../../bower_components/web-component-tester/browser.js"></script>
<script src="../../../bower_components/polymer-gestures/test/js/fake.js"></script>
<link href="../btn-component.html" rel="import">
</head>
<body>
<btn-component id="component"></btn-component>
<script>
function runAfterEvent(eventName, element, callback) {
var listener = function(event) {
element.removeEventListener(eventName, listener)
callback(event.detail);
};
element.addEventListener(eventName, listener);
}
suite('<btn-component>', function() {
var c = document.getElementById('component');
var fake = new Fake();
test('hitting cancel fires cancel event', function(done) {
runAfterEvent('cancel_btn', c, function(event) {
assert.ok(1, "the cancel_btn event should be fired");
done();
});
var cancelBtn = document.querySelectorAll("btn-component /deep/ #cancel_button")[0];
console.log(cancelBtn);
setTimeout(function() {
fake.downOnNode(cancelBtn);
fake.upOnNode(cancelBtn);
}, 1000);
});
});
</script>
The fail happens trying to click the button.
I guess there's a variety of ways to approach resolving this - including in my own tests (e.g. checking the viewport size vs the element position and scrolling right before trying to simulate a click), but starts to get quite fiddly/fragile. A reasonable option might be to add a config to wct that specifies a minimum viewport size on the component iFrame.
Perhaps I'm missing some available configuration that could help here. Is there a recommended way to handle this scenario?
A simple solution is pretty obvious. I added the following to my test's index.html
<style>
#subsuites {
width: 600px !important;
}
</style>
The css used by the wct tool sets the width at 50% and nests frames when using file globs - resulting in progressive narrowing.
I am trying to make a semi-resuseable widget but I am running into a problem. I am trying to encapsulate a some CSS code inside a shadow root so that it does not affect the rest of the webpage but this CSS is used across multiple widgets so I am trying to include a remote stylesheet. None of the examples I have found use a remote style sheet and I was wondering if this was possible.
EX:
<template id="templateContent">
<head>
<link rel="stylesheet" href="css/generalStyle1.css">
</head>
<body>
<div class="affectedByGeneralStyle1"></div>
</body>
</template>
script to include template:
<div id="host"></div>
<script>
var importedData = (html_import_element).import.getElementById("templateContent");
var shadow = document.querySelector('#host').createShadowRoot();
var clone = document.importNode(importedData.content, true);
shadow.appendChild(clone);
</script>
I came across the same problem recently. What I ended up doing was using:
<template id="templateContent">
<style> #import "css/generalStyle.css"; </style>
</template>
Additional info: This worked just fine except that now I'm having some cache issues as Chrome does not seem to reload those resources after a hard reload.
Let add to the answer . Now direct tag is supported in shadow dom.
You can directly use
<link rel="stylesheet" href="yourcss1.css">
<link href="yourcss2.css" rel="stylesheet" type="text/css">
Check they has been update by whatwg and W3C
Useful link for using css in shadow dom.
https://w3c.github.io/webcomponents/spec/shadow/#inertness-of-html-elements-in-a-shadow-tree https://github.com/whatwg/html/commit/43c57866c2bbc20dc0deb15a721a28cbaad2140c
https://github.com/w3c/webcomponents/issues/628
Direct css link can be use in shadow dom
Thanks.
I added the stylesheet's link element directly to the shadow root this way:
let link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.setAttribute('href', 'whatever.css');
this.shadowRoot.appendChild(link);
It seems to work fine. (I called this from the constructor of the component.)
actually polymer has an internal utility to load css links, i have implemented a javascript function that is using polymer internal css processor,so if you want to add css links at runtime you can use it:
Polymer('my-element', {
ready: function () {
this.importCss("path/myfile.css");
},
importCss: function (path) {
var $shadow = $(this.shadowRoot);
var $head = $("<div></div>");
var $link = $("<link rel='stylesheet' type='text/css'>");
$link.attr("href", path);
$head.append($link);
var head = $head[0];
this.copySheetAttributes = Polymer.api.declaration.styles.copySheetAttributes;
Polymer.api.declaration.styles.convertSheetsToStyles.call(this, head);
var styles = Polymer.api.declaration.styles.findLoadableStyles(head);
if (styles.length) {
var templateUrl = this.baseURI;
Polymer.styleResolver.loadStyles(styles, templateUrl, function () {
var $style = $shadow.find("style");
if ($style.length > 0){
$shadow.find("style").append($head.find("style").html());
}else{
$shadow.append($head.html());
}
});
}
}
});
Note: this code needs jquery to run
For some reason, when a user has their display set to 125% from the Control panel, IE9 will add extra width inline to elements like so:
<div class="container" id="main" style="width: 1500px">
<!-- Code goes here-->
</div>
The inline style above (with the width) is the one added by IE9. IE8 does not have this problem, and it's definitely triggered by setting the Windows display settings to 125%. Chrome and Firefox display things properly without the extra style too. Don't suppose anybody has a workaround or fix for this? Can't control what settings the users have, but I've seen other sites render properly.
Ok, so I solved this with a conditional comment and a bit of jQuery:
<!--[if IE 9]>
<script type="text/javascript">
window.onload = function () {
if ( $('#main').attr('style') !== 'undefined' ) {
$('#main').removeAttr('style');
}
}
</script>
<![endif]-->
Basically, it checks to see if IE put a "style" attribute on the offending element, and if so, it removes the attribute.
Yep or if you want to be more selective to width and height
jQuery(document).ready(function () {
removeInlineWidthHeightElements($('#main'));
});
function removeInlineWidthHeightElements(element) {
element.attr('style', function (i, style) {
return style.replace(/width[^;]+;?/g, '').replace(/height[^;]+;?/g, '');
});
}
Is it possible to remove inline styles with jQuery?
I'm building a dummy widget for a iGoogle/Netvibes like portal. This is a "Google Maps" widget, as it only renders a map centered on a specific location.
The widget looks good in all browsers but IE8, in which the height I specify to the <div> that contains the map is not taken into account.
Here's the interesting part of the code:
<body onload="initialize()" >
<div id="map_canvas" style="height:400px; width: 100%;"></div>
</body>
I have no control on the portal, so the only thing I can modify is the widget itself. I also tried to set the height for the <body>, but same thing.
Any idea on why it's not working in IE?
Thanks!
Put this in the page you're calling with the iframe:
<script type="text/javascript">
var iframes = window.parent.document.getElementsByTagName('iframe');
for(var i = 0; i < iframes.length; i ++)
{
if(iframes[i].src == window.location)
{
iframes[i].style.height = '400px';
}
}
</script>
If you are on 2 different domains, this isn't possible, and unfortunately there is no other way when supplying the <iframe> directly to the end-user. The best solution would be to instead give the user a script tag that generates the <iframe> tag using a document.write()
Example script tag to give to your client:
<script type="text/javascript" src="http://www.example.com/widget-getter.js?client=[clientid]&widget=[widgetid]"></script>
Contents of the script that the above tag would call:
document.write('<iframe height="400px" src="http://www.example.com/widget.html"></iframe>');
Did you try using the height attribute of the iframe tag?