HTML not rendering on Salesforce using $sce and ng-bind-html - angularjs

I am using Salesforce as the back end and my users can get some notifications that could contain an tag with a link to somewhere. This being said I have used $sce in the controller to do a function like this:
vm.to_trusted = to_trusted;
function to_trusted(html_code) {
return $sce.trustAsHtml(html_code);
}
In the front end I am using it as such:
<p ng-bind-html="vm.to_trusted(message.body)"></p>
An example of the returned message.body is
Click Here to Fill out your Profile. It will allow you
On localhost this works awesome with the link being shown and not the tag. On Salesforce, this is not the case with the above being shown instead. Any ideas as to why this is not working?
UPDATE:
Yes I do have ngSanitize included :)

The Salesforce #dispatch requests serialize text in an odd manner.
If the content of a Salesforce string is: 'Things' you will see in Angular that you've received: <a href="$quot;>Things<a>
The solution I've found is, in your controller:
function to_trusted(html_code) {
// Cause the &ltg; etc become '<'
return $('<textarea />').html(html_code).text();
}
Because Salesforce.

Related

Drupal Services JSON response format processing with Angularjs

I have a Drupal web service that returns a JSON response in the following format. I can easily access top level notes e.g. title. However, I also need to access the value under body. I can get body.und but not body.und.value. How do I do that? Also the HTML tags are showing as text and I can see all the slashes getting printing in my Angular View.
Update: I have been able to get the the value of the body by using $scope.body
= myresponse.data.body.und[0].value;
Now the only problem is how to process HTML in the body. My Angular framework which is Ionic is showing all the HTML tags e.g. p li etc instead of formatting them.
{"vid":"37","uid":"1","title":"Terms of Use","log":"","status":"1","comment":"1","promote":"0","sticky":"0","nid":"37","type":"page","language":"und","created":"1395878580","changed":"1501982359","tnid":"0","translate":"0","revision_timestamp":"1501982359","revision_uid":"1","body":{"und":[{"value":"THESE TERMS OF USE (\"TOU\") ARE A LEGAL CONTRACT BETWEEN YOU (\"USER\") AND
$scope.body = myresponse.data.body.und[0].value; helped me get access to the value of the body of the node.
ng-bind-html="body" helped me get access to the body of the HTML.

Which method is good to use for laravel 5 and angularjs tag conflict?

I had print value issue in laravel view, i was trying to print $scope value inside laravel blade. I searched about and find two kind of solution.
1- Change angularjs print tag
By this method i can change angularjs print tag.
var app = angular.module('app', []);
app.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
});
app.controller('app', function ($scope, $http) {
$scope.text_print = 'this is text';
});
Now in blade i can print like <% text_print %>
2- Add # for printing angularjs $scope value
I found an up-voted answer in which #Paul A.T. Wilson says that
The easiest way to do this is to simply use # in front of your Angular code
Example #{{text_print}}
Both are working for me, actually i want to make a plugin, so which method should i use? because i'm not sure the second one is compatible with laravel old version. I want my plugin compatible with all version of laravel.
Can anyone guide me about this, i would like to appreciate. Thank You
Changing either interpolation strings for Blade or angular is the best option if you want your plugin to work with older versions of Laravel.
For angularJs you already know how to do it from here.
For Blade, inside your Laravel app's AppServiceProvider.php file add the following code in the boot function:
public function boot() {
Blade::setRawTags("[[", "]]");
// for variables and Blade
Blade::setContentTags('<%', '%>');
// for escaped data
Blade::setEscapedContentTags('<%%', '%%>');
}
Note: In my opinion it's easier to change the interpolation tags for angular as changing the interpolation tags for blade requires you to clear out the storage/framework/views folder.
Apparently there's another way to do this, but I'm not sure if it will work in older versions:
#verbatim
<div>
{{ variableOne }}
{{ variableTwo }}
</div>
#endverbatim
The verbatim annotation indicates that the section is as-is, ie: Blade will leave it out.

Access an angular page from a form

I would like to access an angular page from an html form. But when I submit the form via method get and with parameter I get some problem with the url.
Here is a simple form to reproduce the problem :
<form action="http://ncel28182/pl/Angular/#/FFCO">
<input type="text" name="test">
<button>toto</button>
</form>
When I click on the submit button, it open a page where the url is
http://ncel28182/pl/Angular/?test=#/FFCO
It seems that the parameters are placed before the #.
Is there a way to fix it ?
I believe you should use $location to change location, and a service to share data, as in the following :
HTML :
<form name="myForm" ng-submit="submit()">
<input type="text" name="test">
<button>toto</button>
</form>
Javascript :
function submit($scope, $location, MyService) {
MyService.data = $scope.myForm.test;
$location.url("/pl/Angular/#/FFCO");
}
In the other's page controller, define the service as a dependency and you will be able to access the up-to-date data.
Please note that I'm not a professional angularjs user or even a webdevelopper, you should probably wait for other users to react to my answer or add their own.
Since you can't edit the form sending data, you can't use ngRoute to directly route to the desired "FFCO" view because ngRoute matches against $location.path, whereas the form sends the "FFCO" part as the $location.hash. Since you have no $location.path provided, the form will target your application root.
What you will want to do is add some js code in this page to handle the location change :
if ($location.hash() === "/FFCO") { $location.path("/FFCO"); }
This should do the trick, translating the url requested by the form to a format understandable by your angularjs application. I don't think this will change the hash, if an extra #/FFCO by the end of your URL is a problem you should remove it with $location.hash('').
I believe the best place to do so would be in an extra controller added somewhere after your app bootstrap code.
This is obviously still sub-optimal, I wish I had a better solution.

Linking to external URL with different domain from within an angularJS partial

All I am trying to do is include an anchor tag inside the html of a partial that links to an external site. Were this standard html, the code would simply be:
google
As simple as this is, I cannot seem to find a working solution for getting past angular intercepting the route (or perhaps replacing my anchor with the https://docs.angularjs.org/api/ng/directive/a directive unintentionally?).
I have scoured SO and the rest of the web and seen a myriad of solutions for dealing with: links within the same domain, routing within the SPA, routing within a page (ala $anchorScroll) but none of these are my issue exactly.
I suspect it may having something to do with using $sce but I am an Angular n00b and not really sure how to properly use that service. I tried the following in my view controller:
$scope.trustUrl = function(url) {
return $sce.trustAsResourceUrl(url);
}
with the corresponding:
<a ng-href="{{ trustUrl(item) }}">Click me!</a>
(as described here: Binding external URL in angularjs template)
but that did not seem to do the trick (I ended up with just href="{{" in the rendered page).
Using a plain vanilla anchor link like this:
google
also failed to do the trick (even though some online advised that standard href would cause a complete page reload in angular: AngularJS - How can I do a redirect with a full page load?).
I also tried adding the target=_self" attribute but that seemed to have no effect either.
Do I need to write a custom directive as described here?
Conditionally add target="_blank" to links with Angular JS
This all seems way too complicated for such a simple action and I feel like I am missing something obvious in my n00bishness, at least I hope so because this process is feeling very onerous just to link to another url.
Thanks in advance for any solutions, advice, refs or direction.
It turns out that I did in fact have all anchor links in the page bound to an event listener and being overridden. Since that code was fundamental to the way the page worked I did not want to mess with it. Instead I bypassed it by using ng-click to call the new url as follows:
HTML:
<a class="navLinkHcp" href="{{hcpurl}}" title="Habitat Conservation Plan" target="_blank" ng-click="linkModelFunc(hcpurl)">Habitat Conservation Plan</a>
Controller:
$scope.hcpurl = 'http://eahcp.org/index.php/about_eahcp/covered_species';
$scope.linkModelFunc = function (url){
console.log('link model function');
$window.open(url);
}
And voila! Good to go.
Thanks again to KevinB for cluing me in that this was probably the issue.

How to intercept AngularJS $http logging for display in page

I want to intercept console log message from AngularJS and display them in a div on the page. I need this in order to debug ajax traffic in a PhoneGap app.
This is an example of the kind of errors I want to capture:
I tried this Showing console errors and alerts in a div inside the page but that does not intercept Angular error messages.
I also tried the solution gameover suggested in the answers. No luck with that either. Apparently $http is handling error logging differently.
I guess the answer you tried has the right idea but you're overriding the wrong methods. Reading here I can see angularJs uses $log instead of console.log, so to intercept you can try to override those.
Something like this:
$scope.$log = {
error: function(msg){document.getElementById("logger").innerHTML(msg)},
info: function(msg){document.getElementById("logger").innerHTML(msg)},
log: function(msg){document.getElementById("logger").innerHTML(msg)},
warn: function(msg){document.getElementById("logger").innerHTML(msg)}
}
Make sure to run that after importing angular.js.
EDIT
Second guess, override the consoleLog method on the LogProvider inner class on angular.js file:
function consoleLog(type) {
var output ="";
//arguments array, you'll need to change this accordingly if you want to
//log arrays, objects etc
forEach(arguments, function(arg) {
output+= arg +" ";
});
document.getElementById("logger").innerHTML(output);
}
I've used log4javascript for this purpose. I create the log object via
var log = log4javascript.getLogger('myApp')
log.addAppender(new log4javascript.InPageAppender());
I then use this in a value dependency, and hook into it where needed (e.g. http interceptor).
A more lightweight approach might be to use $rootScope.emit and then have a component on your main page which prepends these log messages to a visible div, but this will require you to change all your calls to console.log (or redefine the function in your js).
I think that this message is not even displayed from AngularJS. It looks like an exception which has not been caught in any JavaScript (angular.js just appears on top of your stack because that's the actual location where the HTTP request is being sent).
Take a look at ng.$exceptionHandler. That should be the code you seem to be interested in. If not, take a quick web search for „JavaScript onerror“ which should tell you how to watch for these kinds of errors.
I would rather user an $http interceptor.
Inside the responseError function, you can set a property on a service that will be exposed to the div's scope.

Resources