angular, directives not running on content being brought in through json - javascript

Sort of a weird problem that I'm not exactly sure what is going on so I will try to be as clear as I can.
I am bringing html content through a json object and placing it in a div. The problem I am having is when I bring html in that runs javascript in through a directive, it does not seem to be running. For example - I'm playing around with this http://cmaurer.github.io/angularjs-nvd3-directives/ , a d3 directive for angular.
If I have the html on the template it works fine - I'm using an example from their page that looks like so -
<nvd3-stacked-area-chart data="exampleData" id="exampleId" showXAxis="true" showYAxis="true" showControls="true" width="700" height="200"> <svg></svg> </nvd3-stacked-area-chart>
This works fine when placed on the page, however when I bring it in through the json, it seems the directive (or angular? ) is not running on it.
For reference the part of the json comes in like this -
'content' : '<nvd3-stacked-area-chart data="exampleData" id="exampleId" showXAxis="true" showYAxis="true" showControls="true" width="700" height="200"> <svg></svg> </nvd3-stacked-area-chart>',
then is bound like this
ng-bind-html="widget.content"
This seems to work fine, if I inspect the element I can see the correct html sitting there. I have a $sce.trustAsHtml inside my controller to make sure it's properly escaped.
So I'm not sure how to approach this issue, because there are no specific errors thrown, so I'm not sure if it's angular, or the directive, or the order of events? Is there a way to re-initialize the d3 directive for example on this once the html content is loaded into the div?
I'm not sure where to begin with this, so I would much appreciate any insight. Thank you for reading!

By the time you load the content received by wire, angular has already finished compiling and linking the page. therefor, you need to tell it to recompile. Have a look at this SO and try to call $compile by hand after receiving the content and placing it in the div: How do I make angular.js reevaluate / recompile inner html?
Keep in mind though that this is rather tricky business and you should really check the security of what you're doing.

Related

Transcluding without running digest on contents (passing raw HTML) in Directive

I am trying to pass raw HTML inside a directive for later transclusion (when I open a modal - I will use the HTML to populate it)
The problem is - that if I do it like this, the contents of dialog-body get run and the ng-repeat is implemented, which means when I pass the template along, it gets run again causing an ahem stack overflow.
Is there a way for me to use transclusion or something else to pass the inner HTML without running any digest on it?
<dialog-body>
<div ng-repeat="item_value in item.values">
{{item_value.string}}
</div>
</dialog-body>
By the way, I figured out how to get this done.
Angular was running ng-repeat on the initial code, then re-running it once I used it later on. To avoid this - I did this to skip the first ng-repeat run:
<dialog-body ng-non-bindable>
<div ng-repeat="item_value in item.values">
{{item_value.string}}
</div>
</dialog-body>
This meant that I was only passing the actual HTML and not running Angular on it. I then used a querySelector to find all the ng-non-bindable attributes and remove them. Seems to work fine.
Hope this helps someone!

Is Angular usable in Content Script

I have a Google Chrome extension that injects a content script on given page of a site. This content script replaces the action bound to a button. When the button is clicked, some HTML elements are added (a foundation popup). I want to use Angular to manage the popup I add to the page. Can I do this ?
Here is sample HTML code that could be added when the button is clicked.
<div ng-app="MyApp">
<div ng-controller="MyCtrl as ctrl">
<p> {{ctrl.sayHello()}} </p>
</div>
</div>
Will this work? (I haven't gotten it to work yet, but I'm still trying) If it works, what if the page already contains another Angular app?
After my HTML insertion, the HTML might look something like:
<html ng-app="PageApp">
<body ng-controller="PageCtrl">
...
...
<div ng-app="MyApp">
<div ng-controller="MyCtrl">
...
</div>
</div>
</body>
</html>
Edit: I have found angular.bootstrap(). So I can launch an Angular module on a given DOM element (my div). I think it could be a good solution. Can I still use it if Angular has already tried to load an ng-app directive and failed? Because it will certainly happen when injecting Angular code, and trying to load a PageApp that is not defined for me.
What #estus is saying is correct, and answered your question. Your code will not work, since "[you] can't have nested Angular apps", in other words an Angular app cannot have another Angular app inside of it, regardless of whether you have access to the source (which you probably do, since you're injecting code).
Suggestions
More radical, but note that most, if not all of AngularJS's functionality can be ported to vanilla JavaScript quite easily, if you ignore the attribute binding. You might have to write more specific and manual code, but this would cut any Angular-related problems out of the picture.
There is a hackish workaround that may allow you to nest some Angular apps, but this also requires access to the source of the page in which you're injecting the code, and some crazy DOM searching and manipulation, which may not be too efficient.

AngularJS losing two way binding after JS form plugin rendering

I'm hoping someone with a better understanding of AngularJS might be able to shed some light on whats going on here.
I have a webpage with a long form. After the JS form plugin is initialized, everything in the form no longer has two way data binding. JS plugin for reference can be found here
If I remove the id link to the JS plugin, thus not applying or rendering the steps plugin, all two way data binding works as expected.
I could post a lot of code here but I'm not sure that would help. I have no problem posting code at any request.
Any ideas on why the two way data binding is losing effect after rerendering a form tag and its contents?
I was actually able to get AngularJS to work correctly with this plugin by including the plugin at the bottom of the page instead of the top. So I think the key here was to let AngularJS load up first, then the page, then the jQuery Steps plugin (at the boom of the page that uses it).
Thanks all for your comments!
Jquery library should include before angular library otherwise your site will try to use jquery instead of angular own lite jquery which will definitely break the binding.

Angular loading template inline

In an angular js 1.2.22 version code, I saw this in the HTML
<div class="mainContent" ng-include="content"> </div>
and in its corresponding controller, I see this.
$scope.content = 'templates/contents/home.html';
I see its making an Ajax call to load the template.
I am working on improving the speed of the content display and I did some optimizations like minifying the javascript code and minifying css
My doubt is how to make this inline - without making the Ajax call. So, that I could check if there is visible difference in speed of the content showing up for this template?
I tried the gulp-angular-templatecache to cache templates but, it did not work.
Is there any workaround for this so that I can make this template inline ?
What you're looking for is Angular's $templateCache.
Depending on your task runner, you might want to give gulp-angular-templatecache or grunt-angular-templatecache a try.

Executing JS in dynamically loaded content

I've started working on a project that loads all of the different pages content dynamically.
On the surface this seems simple enough, an AJAX call to a script that returns the content that is placed inside a DIV. Except that not only HTML but JS is returned as well. I'm seeing a lot of things like this:-
<img src="spacer.gif" height="1" width="1" onload="SOMEJSHERE"/>
Dotted in the code to execute JS functions. This doesn't provide the kind of HTML/JS code separation I've come to love using JQuery.
I can understand that they don't want to load all the JS and HTML at once, there is an awful lot of it... But this just doesn't feel like the best way.
Some experience and suggestions please?
Lyle
Have a look at the jQuery .live() event. It can apply behaviors (event bindings) to all current and future elements on the page, which match the given selectors.
This means that your newly-loaded HTML need not contain any script. Just make sure the loaded elements have the right selectors (class names and id's).
hey i use "eval" to execute js dynamically.
e.g.
<script>
var strjs = 'function execute(){alert("foobaring");} execute();';
eval(strjs);
</script>
In the end I used the tabs.select option from JQuery UI (which we were using for the ajaxed pages) and executed the appropriate JS as needed.

Categories

Resources