Links not working with ng-bind-html on mobile - angularjs

I'm building a mobile app with Ionic using AngularJS.
In some of the views I would like to bind HTML code having multiple links, but somehow its not working on mobile.
In the browser it works just perfectly, but on mobile the link can not be clicked.
Text I would like to bind:
"Some text http://www.test.com"
My code in HTML:
<p ng-bind-html="testDetails"></p>
$sanitize is available, ngSanitize has been added as a dependency
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular-sanitize.js"></script>
var appControllers = angular.module('starter.controllers', ['ngSanitize']); // Use for all controller of application.
Any idea?

Looks I've found a solution.
Somehow simple <a> tags with href attribute does not seem to be working on mobile with ng-bind-html.
Instead, I used:
<a href="" onClick="window.open('http://www.test.com', '_system', 'location=yes')"
target="_blank">http://www.test.com</a>
This just works perfectly, but it was necessary to bypass $sanitize in ng-bind-html by explicitly trusting the dangerous value (See AngularJS documentation).
https://docs.angularjs.org/api/ngSanitize/service/$sanitize
In Controller:
$scope.testDetails = '<a href="" onClick="window.open('http://www.test.com', '_system', 'location=yes')"
target="_blank">http://www.test.com</a>'
$scope.deliberatelyTrustDangerousSnippet = function(sniptext) {
return $sce.trustAsHtml(sniptext);
};
In HTML view:
<p ng-bind-html='deliberatelyTrustDangerousSnippet(testDetails)'></p>
Also I've found a good filter to do this work, if the data is received with simple <a href="">attributes:
https://gist.github.com/rewonc/e53ad3a9d6ca704d402e

Related

Get fullcalender HTML-Elements with AngularJS and change them

I'am using fullcalender and need to change some navigation buttons with AngularJS. I do not have much experience with AngularJS so the JS Code would be somthing like this:
var filter = $(".fc-filter-button");
filter.html("<i class='fas fa-filter'></i>");
filter.attr("id", "dropdownFilterButton");
But how can i archive this and some other usual JS/JQuery Tasks with AngularJS. I know i can use JQuery too but want to do it in the right Angular way.
I tried something like this:
element[0].getElementsByClassName('fc-filter-button').html("<i class='fas fa-filter'></i>")
or
var queryResult = element[0].querySelector('.fc-filter-button');
angular.element(queryResult).html("<i class='fas fa-filter'></i>")
How can i make these changes without touching the fullcalender code itself.
Take a look at the NgSanitize module "The ngSanitize module provides functionality to sanitize HTML".
Here's an basic example which should get you going in the right direction
angular.module('app', ["ngSanitize"])
.controller('myCtrl',function($scope){
$scope.content = "<p>The initial html</p>";
$scope.changeHtml = function(){
$scope.content = "<h3>The changed html</h3>";
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.2/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.2/angular-sanitize.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<button ng-click="changeHtml()">Change html</button>
<div ng-bind-html="content">
</div>
</div>

angular1 with electron: ng-dblclick not working

I am using electron with angular 1.6.4.
I have a controller, in which I dynamically generate li. I want to bind a double click event on this list items, but I could not succeed.
function TheController($http, $scope, KeyService) {
$scope.openItem = function(id) {
console.log(id);
}
var key = KeyService.getLastKey();
connectToBackend($http,key);
}
function connectToBackend($http, key) {
$http.get(ENDPOINT).then(
function(result) {
//do some work
document.getElementById("list").innerHTML += `<li draggable="true" ondragstart="itemDrag(event)" id=${theID} ng-dblclick="openItem(this.id)"><i class="fa fa-folder-open"></i> ${result}</li><hr>`;
},
function(e) {
//error
}
);
}
If I double-click here, absolutely nothing happens - not even an exception.
If I use ondblclick, it works if I define openItem in renderer.js. But I'd rather like to have it defined inside TheController, to keep some order and to be able to access injected services.
Is this possible? Is the drag stuff maybe interfering?
The directly appended html wouldn't work until you compile it. You should manually compile it before injecting it into DOM tree.
document.getElementById("list")
.appendChild($compile(`
<li draggable="true" ondragstart="itemDrag(event)"
id=${theID} ng-dblclick="openItem(this.id)">
<i class="fa fa-folder-open"></i> ${result}
</li>
<hr>`)($scope);
Generally doing DOM manipulation from directly controller is anti-pattern as it makes your controller code to more tightly coupled with view/html.
Rather I'd suggest you to use ng-inlcude directive and place custom template in ng-template script. So that it will available any time inside $templateCache of angular.
<script id="myCustom.html" type="text/ng-template">
<li draggable="true" ondragstart="itemDrag(event)"
id="{{theId}}" ng-dblclick="openItem(id)">
<i class="fa fa-folder-open"></i>
<div ng-include="ENDPOINT"></div>
</li>
</script>
and then your html will look like below.
Html
<div id="list">
... Your content ..
</div>
<div ng-include="'myCustom.html'"></div>
If you noted, I directly used ENDPOINT directly inside ng-include for the same to work, you have to do some additional setting
angular.module('myApp').config(function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist([
// Allow loading from outer templates domain.
'http://somedomain.com/templates/**' //ENDPOINT domain should white listed here
]);
});
Also ondragstart wouldn't call your controllers method, until you patch it up with angular wrapper directive. There are third-party library available out there, you could use any one of them.

AngularJS - looking to add and remove an iframe based on dom events

I would like to add an iframe to a page when certain links are clicked and remove it when other mouse events happen on the page. From what I can see, it seems that using an AngularJS directive would be the best way to do this. What I'm not sure about is what is the best way to format the directive. I'm thinking of making the directive at the attribute level...something like this:
<div myIframeDirective></div>
What I'm not sure of is the best way of removing/adding the directive contents (an iframe and a header above it) when various click events happen on the main page. Not looking for anyone to write the code for me...just looking for examples of how this can be best accomplished.
You should be using ng-if.
<iframe src="http://www.example.com/" ng-if="showIframe"></iframe>
<button ng-click="showIframe = !showIframe">Click me to show/hide the iframe</button>
Here's a working example:
var app = angular.module('app', []);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<iframe src="http://www.example.com/" ng-if="showIframe"></iframe>
<button ng-click="showIframe = !showIframe">Click me to show/hide the iframe</button>
</div>
In Angular, ng-if will remove the iframe from the DOM if it is false.
This means the URL will NOT be requested until ng-if is true.
<iframe ng-if="frameDisplayed" ng-src="{{src}}"></iframe>
And use the link
Toggle
Then in your controller, you can control what your iframe display:
$scope.src = 'https://angularjs.org';

Angular binding for dynamically added html div

Sorry, this seems a duplicated questions, but I tried all answered questions close to my question, with no success.
I am trying to introduce angular.js into a legacy system.
the system is using the .load jquery function to dynamically load div content with a page from an ASP.NET MVC page.
my brief html will look like this
<body ng-app="myApp">
<div ng-controller="myCtrl">
any content...
<div id="dyncontent"> </div>
</div>
and my javascript legacy code looks like
$('#dyncontent').load('/showviewcontent');
I added in the dynamic content, some angular directive and binding instruction
my angular code is like this
var myApp = angular.module('myApp', []);
myApp.controller('myCtrl', function ($scope) {
.....
});
How to make the binding / angular directive works on the newly added content?
You need to manually start the angular module using angular.bootstrap
$('#dyncontent').load('/showviewcontent', function() {
angular.bootstrap(document.getElementById('dyncontent'), ['myApp']);
});

Calling Javascript within ng-if

I have some legacy jQuery code. It's a big chunk of code, so I would prefer to port it a little while later. To use it, I call $('#legacyId').legacyFunction().
Here's the deal, though.
I have an ng-if. And within that ng-if, I have the JavaScript where I call my legacy function.
<div ng-if="status=='yes'">
<div id="legacyId">
I am a legacy div!
</div>
<script type="text/javascript">
$('#legacyId').legacyFunction()
</script>
</div>
It looks like this JavaScript is being called when the page loads. Though I load angular after jQuery, it seems that angular removes the section under control of the ng-if, and therefore the jQuery function on #legacyId fails.
Any ideas? Thanks!
Edit-note: I import jQuery and the legacy code that extends jQuery at the top of my HTML document. Angular is loaded at the bottom of the document.
Edit-note 2: I have also tried <div ng-init="$('#legacyId').legacyFunction()"></div>, but I get an error, Error: [$rootScope:inprog] $apply already in progress.
Okay, managed to work this out.
In the HTML:
<div ng-if="status=='yes'">
<div legacy-directive>
I am a legacy div!
</div>
</div>
In my app code:
app.directive('legacyDirective' , function() {
return {
link: function(scope, element, attrs) {
$(element).legacyFunction(scope.$eval(attrs.legacyDirective));
}
}
});
Because of the $(element).legacyFunction(scope.$eval(attrs.legacyDirective));, it looks like I can also pass parameters to the legacyFunction; e.g. <div legacy-directive='{myParameter: true}>
Thank you for all who answered! You set me on the right track.

Resources