I am trying to use an tag in HTML to open a new modal browser window with a url that is retrieve through an Angular value, as so:
Test Link
The rest of my angular markup works just fine, but the above anchor does not work. In several attempts I'm made, I either don't get a value at all (null), or the resulting URL is marked as "unsafe".
I've tried calling a method within my controller to pass back the value, but same failures.
Am I going about this the wrong way?
Note: OpenPopUpPage is a built-in SharePoint function that I'm using, but I could just as well call window.open or something else. But I think that is immaterial to this problem.
UPDATE: I have create a jsfiddle (warning, first-timer), and attempted to follow a couple of the responses here as a demo, but I can't get any of them to work correctly. My jsfiddle
What you have isn't a normal link. It's more of a <button>, although it could go either way.
The angular way of handling the click to open a new window would then be:
<button type="button" ng-click="$ctrl.click($event)">...</button>
and in your angular code:
function Controller/Copmponent/Directive/Whatever() {
this.url = 'http://example.com';
this.click = function () {
open(this.url, this.target, this.options);
};
}
If your page needs to support JavaScript disabled, or if you weren't in angular land at all, it may be reasonable to use an <a> element provided that you give the href a valid URL:
...
.controller('controllerName', ['$scope', '$window',
function($scope, $window) {
$scope.redirectToNewPage = function(){
$window.open('https://www.google.com', '_blank');
};
}
]);
I wanted to add this final answer, since while others provide good examples for opening pop-ups or new windows, the main objective was to be able to open a new window to a location that was passed from an angular/REST query value.
The answer was 2-part:
1) Use ng-click along with a function/method inside of your controller to handle the opening of the new window. Avoid trying to use javascript directly within the . Thanks all who contributed to this lesson for me.
2) Also, when passing a value to a function that is coming from your controller query output, don't include the {{}} around your passed value, as apparently that is only for diaplaying data, not passing it.
So here's the resulting code:
//HTML:
<button type="button" ng-click="foo(myController.LinkValue)">Let's Do This</button>
//Code within Controller:
$scope.foo = function(myURL) {
open(myURL, 'popup', 'width=300,height=200');
};
Related
I just started using the ngTagsInput angular library and I am having issues with it updating the model. I show the tag input in an ionicPopup and interestingly the on-tag-added event fires which shows that $scope.sites[] IS populated.
When I call $scope.test() the array is empty. The only context in which it holds a value is the method tied to the on-tag-added event.
Here is a simplified controller example:
$scope.sites = [];
$scope.addSites = function() {
// this works
console.log("In addSites");
console.dir($scope.sites);
}
$scope.test = function() {
// in any other method $scope.sites is empty
console.dir($scope.sites);
}
In my view I have the tag element defined as:
<tags-input ng-model="sites" add-on-space="true" placeholder="Add Site Numbers" on-tag-added="addSites($tag)"></tags-input>
I find it incredibly strange that a $scope variable can contain the values I expect within the context of the library event but not outside of that.
Is there anything special that needs to be done in terms of binding? As far as the documentation goes I don't see what I am missing. Any suggestions would be much appreciated.
After a lot of trial and error I ended up solving this by doing the following.
<tags-input ng-model="$parent.sites" add-on-space="true" placeholder="Add Site Numbers" on-tag-added="addSites($tag)"></tags-input>
I was already passing 'scope : $scope' in my call to $ionicPopup({}) but without the ng-model set to "$parent.sites" it wasn't binding correctly.
Hopefully this saves somebody down the road from pulling their hair out!
I am working on enhancing a feature of an already deployed application. All the js code is minified and i only can excess html files. I need to call a function on-click of a 'div' which parse some elements and open a new tab with resolved url(url updated with help of parsed elements).
My initial thought is to make a function in a new js file and add link to it on main html page. Evidently the call to function is fine with on click attribute call on the div. But while passing the angular controller parameters it throws error -
<div onclick="jumpToPage({{vm.username}})"></div>
function jumpToPage(user){
console.log(user);
};
Note - I don't have access to update minified files and i know i can un-minified it but there are lot of files and process is too long.
Please let me know how to resolve/pass parameter to JavaScript function
It should be onclick="jumpToPage(vm.username)">
If you pass {{vm.username}} it will get evaluted.
e.g. vm.username ="some_name"
so,your controller will get some_name and not referance to vm.username
and
it try to search for the same refarance.If it not find then throw exception.
try to use ng-click, when we use ng-click we don't need to use {{}} anymore, since it is automatically bind the model.
I am completely new to ANgularJs. As part of one project my page should show some content dynamically is changes in database. This changed vale can be obtained by a http get.
Before I try the complete scenario, I just wanted to see if is working atleast locally by taking a local variable. But its not working please suggest me how do I handle this.
angular.module('MyApp') .controller('HomeCtrl', function HomeCtrl($scope, $alert, $auth,$location) {
Counter=10;
Counter=Counter+1;
$scope.user={};
$scope.user.counter=Counter;
}
HomeCtrl($scope,$alert,$auth,$location);
);
It looks like you need to remove the following line:
HomeCtrl($scope,$alert,$auth,$location);
As you are still in the controller function call
remove
HomeCtrl($scope,$alert,$auth,$location);
but there were some other things also wrong..
working version:
fiddle -- http://jsfiddle.net/beLbv6L1/
I am trying to bind the following json response in my html page.
The json is as follows:
{
"key":{
"text":"<p>For more information, please visit Support .</p>"
}
}
html page
<div ng-bind-html="message"></div>
Controller Code
$http({
method: 'GET',
url:'DAYS.json'
}).success(function(responsedata) {
$scope.message=responsedata.key.text;
}).error(function(responsedata){});
customizeWindow function inside controller
$scope.customizeWindow = function(url) {
window.open(url, "_blank", "toolbar=yes, scrollbars=yes, resizable=yes,top=70, left=190, width=970, height=460");
}
The ng-bind-html binds the html tags but it strips off the javascript and ng-click event.
i get only Support when i inspect element and the link does not work.
Please suggest me a solution.
This happens since angular Automatically uses $sce -> Strict Contextual Escaping. it allows you to ng-bind-html but it doesn't allow you to add possibly malicious code like JS.
What you are after is explicitly trusting that segment as HTML.
therefore:
angular.module('app', ["ngSanitize"]) // You have to include ngSanitize or it wouldn't work.
.controller('Ctrl', function ($scope, $sce){
$scope.htmlData = <p>For more information, please visit Support .</p> //Took from your example.
$scope.$watch("htmlData", function(newValue){
$scope.trustedData = $sce.trustAsHtml(newValuew);
});
});
HTML Usage:
<p ng-bind-html="trustedData"></p>
Angular Resource:
Strict Contextual Escaping (SCE) is a mode in which AngularJS requires
bindings in certain contexts to result in a value that is marked as
safe to use for that context. One example of such a context is binding
arbitrary html controlled by the user via ng-bind-html. We refer to
these contexts as privileged or SCE contexts.
As of version 1.2, Angular ships with SCE enabled by default.
read on : Angular on SCE - trustAsHtml method
ng-bind-html content is sanitized by default and its not meant to bring DOM into the page. You would use this method to bring content onto the page. Eg if you have a rich text editor - you want to feed it html content, however sanitized and thats when you use ng-bind-html.
For your purpose I would suggest to use templates or plain model binding.
Source of your json, what ever that is should not really know anything about the consumer side (your page) implementation/technology what if you move away from angularJS and start using Knockout, you will have to change server-side as well, because Knockout will have no idea about ng-click. Just pass back the content like http://www.google.com, 'For more information, please visit' and bind it.
{
"key":{
"textsource": {
source : 'http://www.google.com',
message : 'For more information, please visit '
}
}
}
<p>{{textsource.message}}<div ng-click="customizeWindow(textsource.source)\">Support</div> </p>
If you can't change server side, have a look at this example :
1) tell $sce your content is fine
$scope.message = $sce.trustAsHtml(json.key.text);
2) recompile your dynamicaly added content
$scope.init = function () {
var el = document.getElementById("dynamic");
$compile(el.childNodes[0])($scope);
};
NOTE: the recompile step is manual for now (press the recompile button). Follow this to make it work nicely.
I'm trying to use the Angular-UI TinyMCE directive in my Angular app.
What happens is, I query an endpoint, it returns an array of objects. I have a function that then converts that to a long string with HTML tags in it. Then that data is set to a $scope.tinymceModel
This all works fine. I can console.log($scope.tinymceModel) and its the proper data.
The problem is the HTML parse function needs to run after the endpoint query is returned. So I've called the function inside the .success() callback. For some reason when I set the $scope.tinymceModel inside of the callback the TinyMCE directive ignores it. Even if I make it $scope.tinymceModel = 'test' but if I place $scope.tinymceModel = 'test' outside of the callback it shows up in tinymce just fine.
This tells me that for some reason when the TinyMCE directive is loaded it needs the tinymceModel to already be populated with data. I'm not sure how I get around this.
This also tells me that I may have another problem after this. The next task with TinyMCE is the user can then edit the text, click a button and the app will send a POST with the updated info inside tinymceModel If this was a regular text box it would be simple because of the data-binding. However it seems TinyMCE doesn't play well with databinding.
Any ideas?
I've attempted to recreate what you're describing (substituting $http with $timeout) to no avail. Here's my solution and it seems to be working just fine.
HTML:
<div ng-controller="MainCtrl">
<textarea ui-tinymce="" class="form-control" ng-model="someHtml"></textarea>
</div>
JavaScript:
angular.module('testTinymceApp')
.controller('MainCtrl', function ($scope, $timeout) {
$timeout(function() {
$scope.someHtml = '<h1>HELLO THERE</h1>'
}, 7000);
// This does the same thing with an XHR request instead of timeout
// $http.get('/some/data/').success(function(result) {
// $scope.someHtml = '<h1>HELLO THERE</h1>'
// });
});
I thought maybe you could compare with your own application? I know for a fact that this works with XHR requests. I'm building a CMS at work that uses what I assume is an identical workflow.
The someHtml attribute in this snippet will also be valid HTML under the covers, so sending it back in a POST request should be extremely easy.
If this is not sufficient, please provide further explanation.
Figured it out!, the issue has to do with a bug in the TinyMCE Directive. By default there is no priority set. Setting it to a value of 1 or higher fixes it. It seems that the current version of Ui-TinyMCE Directive has this fixed, but the version I pulled down less than a month ago didn't have it fixed.