I'm trying to update scope value on parent window from a child popup.But whenever I try to access the parent window scope,it returns undefined. As it involves two window, I couldn't create a fiddle for this. Code sample is pasted below.
Main page (main.html)
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script>
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.name = 'Superhero';
}
</script>
</head>
<body ng-app="myApp">
<div id="ctrl" ng-controller="MyCtrl">
Hello, {{name}}!
<input type="button" value="Open popup!!" onclick="window.open('child.html');"/>
</div>
</body>
</html>
Child window (child.html)
<!doctype html>
<html >
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script>
function change(){
var e = window.opener.document.getElementById('ctrl');
var ae = angular.element(e);
var s = ae.scope();
s.name="New Superhero";
s.$apply();
}
</script>
</head>
<body>
<input type="button" value="Update parent scope!" onclick="change();"/>
</body>
</html>
Here whenever I try to access scope from the angular element , as shown above in change method, it returns undefined [ae.scope()].But when the same code moved to a function in parent window [only difference in how 'ctrl' element is being accessed], it worked fine and I was able to update the scope variable. Can anyone point out what actually is going wrong here? Thanks
Use the angular reference from the opener:
function change() {
var s = window.opener.angular.element('#ctrl').scope();
s.name="New Superhero";
s.$apply();
}
I had a similar need and had the same problem accessing the scope using angular.element. I was was able to solve it as follows though:
In your main/parent controller do something like this:
$scope.food = 'Mac & Cheese';
window.$windowScope = $scope;
$window.open('views/anotherWindow.html', '_blank','menubar=yes,toolbar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes,personalbar=yes');
Then in the child window controller you can access $windowScope like this:
$scope.parentWindow = window.opener.$windowScope;
console.log($scope.parentWindow.food);
An alternative to putting data directly into the scope would be to use $window scope to broadcast and/or emit events, which is the preferred way of cross-controller communication in angular.
Related
I want to access a variable in iframe from parent index.html.
The index.html:
<!doctype html>
<html lang="en-us">
<head>
<title>Test</title>
</head>
<body>
<p>Test</p>
<div>
<iframe name="myIframe" id="test1" src="index2.html" width="100px" height="100px"></iframe>
</div>
<div>
<script type="text/javascript">
var clickParent = document.getElementById("test1").contentDocument.clicks;
function onClickP() {
console.log("click on parent: " + clickParent);
};
</script>
<button type="button" onClick="onClickP()">Click Parent Button</button>
</div>
</body>
</html>
The iframe index2.html:
<!doctype html>
<html>
<head>
<title>Clicks</title>
</head>
<body>
<script type="text/javascript">
var clicks = 0;
function onClick() {
clicks += 1;
console.log("click counts: " + clicks)
};
</script>
<button type="button" onClick="onClick()">Click Child Button</button>
</body>
</html>
In the console, the variable clickParent is "undefined". How to fix this and make the variable clickParent = clicks?
This question is not a duplicate of Sharing global javascript variable of a page with an iframe within that page because it is the opposite. I want to access the iframe's variable from the parent, not access parent's variable from the child. My Question, the variable that parent accesses from iframe is "undefined".
Any answers would be appreciated. Thank you.
Possibly a duplicate of this.
Declare global variables in the parent and set them in the iframe document using parent.var_name.
You can also access child vars by creating an object for the child document:
child_iframe = document.getElementById("iframe_id").contentWindow;
alert(child_iframe.var_name);
In my case, I was using the window.name on the parent. For accessing that on iFrame, I was using window.parent.name.
I am making a simple program, where if a person types a word 'alpha', the form gets all its elements states ng-prestine/ng-touched/ng-valid/ng-invalid all to their initial states. I think I am doing it correctly but getting an error in console.
HTML
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<form name="form1">
<input type="text" ng-model="person">{{person}}
<button ng-click="click()">Click</button>
</form>
<script>
//Module Declaration
var app = angular.module('myApp',[]);
//Controller Declaration
app.controller('myCtrl',function($scope){
$scope.click = function(){
if ($scope.person = "alpha"){
form1.$rollbackViewValue();
}
}
});
</script>
</body>
</html>
Error
Reference
https://docs.angularjs.org/api/ng/type/form.FormController
Can someone help me out?
The form form1 isn't a defined variable in your controller. You have to use $scope.form1.$...
But be aware that $rollbackViewValue might not do what you expect. It would be easier to set the state you want your form to be in manually.
I've got the following code:
<!DOCTYPE html>
<html>
<body>
<div ng-app="">
<p>Name: <input type="text" ng-model="name"></p>
<p ng-bind="name">{{$http.get('https://api.themoviedb.org/3/movie/now_playing?api_key=b4e5192d902f5add71f4a431c004d734').success(successCallback);}}</p>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script>
$http.get('https://api.themoviedb.org/3/movie/now_playing?api_key=b4e5192d902f5add71f4a431c004d734').success(successCallback: 'JSON_CALLBACK');
</script>
</body>
</html>
But it is not returning anything, how do I make it so I can at least just display everything in that API? I would like to assign it to an variable and be able to explode it for manipulation.
You need to first define an app and a controller, and call $http inside it. In your HTML you can display the data that gets passed into the callback. Something like this:
<!DOCTYPE html>
<html>
<body>
<div ng-app="App" ng-controller="Ctrl">
<p>Name: <input type="text" ng-model="name"></p>
<p>{{ data }}</p>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script>
angular.module('App', []).
controller('Ctrl', function($scope, $http) {
$http.get('https://api.themoviedb.org/3/movie/now_playing?api_key=b4e5192d902f5add71f4a431c004d734').success(function(data) {
$scope.data = data;
});
});
</script>
</body>
</html>
You have a syntax error in your $http.get call. The options inside of .success need to be surrounded with curly braces, as they're an object.
Also, you're trying to use $http before it's been defined.
The http call should be made in a controller. Angular services are not accessible directly in the html or immediately in a script block. I'm sure if you checked the console window you would see at least a couple of errors in what you have put here.
Basically when the data is returned the controller can assign the returned data onto a variable on the scope.
I'm going to guess your new to angular in which case there are many great resources online to guide you though making these first basic steps. Checkout https://egghead.io/articles/new-to-angularjs-start-learning-here.
Is it possible with javascript/jQuery to create objects on page load (or (document).ready) and then later use them, for example on keyup on an input.
If so, how?
If you put all code in $(document).ready{all code here} then your variables won't go out of scope.
$(document).ready(function(){
var someObject={};
$("selector").click(function(e){
console.log(someObject);
});
});
If you're using onclick in html then I'd advice you to change that and move all JS code to JS file or <script> block (not in your html).
Instead of putting many variables on global scope you can namespace it (if you can't put all code in $(document).ready).
var myApplication = myApplication || {};//if myApplication doesn't exist then create it
myApplication.someObject = {};
Then even if your JS is spread over several files you can still maintain one myApplication object.
As gp mentioned; you can use data to add data to html elements:
$("#somebutton").on("click",function(e){
$(this).data("someObject",{});// you can use e.target instead of this as well
});
Below find a example usage.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
TODO write content
<div id="MytextID">My text </div>
<input type="text" id="inputId" name="name">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
var x = $('#MytextID');
$('#inputId').keyup(function(){
alert(x.text());
})
})
</script>
</body>
</html>
script of iframe
<script type="text/javascript" >
var a=5;
</script>
script of parent window
<script type="text/javascript" >
function close()
{
var check=document.getElementById("iframeid").contentDocument.a;
alert(check)
}
</script>
I want to access the variable which is defined inside the iframe from parent. But the above code doesn't work properly can anyone give an idea to implement this.
Using contentWindow instead of contentDocument works for me:
var check = document.getElementById("iframeid").contentWindow.a;
Also, ensure that the domains match and that you are using a webserver to test (I got a protocol warning when testing from the file system).
UPDATE: You're almost definitely better to use the postMessage API.
One method that has always worked reliably for me is for the iFrame to give its parent a reference to its own window when it first loads. The parent can then access all the variables through that reference. This does require that the parent is loaded before the iFrame, but for me that is usually the case.
So in the parent
var iFrameWin;
Then in the iFrame at some point after it has loaded and settled down
parent.iFrameWin = window; //parent now has a ref to the iframe's window
Then, in the parent when it wants a global var contents from the iFrame
alert(iFrameWin.ivar); // shows value if the global 'ivar' in the iFrame
script of iframe:
var a = 5;
window.parent.postMessage(['varA', a], '*'); // put this in some sort of function, ready, or whatever - you can call it multiple times if you need to as the code in the parent is an eventListener
script of parent window:
var b;
// you might want to write these into if statements to make sure that e.data[0] is varA if you have multiple messages coming across
if (typeof window.addEventListener != 'undefined') {
window.addEventListener('message', function(e) {
b = e.data[1];
}, false);
} else if (typeof window.attachEvent != 'undefined') { // this part is for IE8
window.attachEvent('onmessage', function(e) {
b = e.data; // you'll probably have to play around with this part as I can't remember exactly how it comes across in IE8 -- i think it will involve slice() iirc
});
}
Most of my knowledge on this topic comes from Ben Vinegar's talk on Seamless iFrames
This is a cross-domain "okay" method to deal wit this stuff. I'm sure there are some security holes, just as with anything on the web.
See if this works for you:
i created this parent.html page and put an iframe in it with a text input which will show the value passed from iframe window:
<html>
<head>
<title>IFrame Example</title>
<script language="javascript">
function hello(string){
var name=string
document.getElementById('myAnchor').value=name;
}
</script>
</head>
<body>
<iframe namne="iframe" id="iframe_id" src="inputForm.html" height="150" >
</iframe>
Name: <input type="text" id="myAnchor" >
</body>
</html>
and this iframe content page:
<html>
<head>
<title>IFrame Child Example</title>
</head>
<body>
<form name="frm2" >
<h1><font color="#000099">Input Form</font></h1>
<p>Name : </p><input type="text" name="resp" id="input" value=""/>
<input type="button" onclick="parent.hello(this.form.resp.value);" value="Submit" />
</form>
</body>
</html>
clicking the button i get the value in my parent window.
Play with it if you get something with this one.
document.getElementById('ID_OF_IFRAME').document.getElementById('f1')
Note that cross-domain restrictions will still apply.
This is how SharePoint do it when passing argument values from the parent window to the iframe. It's simple, but it works.
<html>
<body>
<iframe id="iframe1"></iframe>
<script type="text/javascript">
var ifr = window.document.getElementById("iframe1");
ifr.dialogArgs = "Hello from the other side.";
ifr.src = "iframeContent.html"
</script>
</body>
</html>
Inside iframeContent.html:
<html>
<body>
<input type="button" value="Click Me!" onclick="alert(window.frameElement.dialogArgs);" />
</body>
</html>
The other way around (accessing ifr.dialogArgs from the parent window after having its value modified by the iframe document) also works.