I'm working with AngularJS.
One of the (technical) requirements is to fetch the "ng enabled" HTML content from the server, in response to a click event, and inject it into a <div ng-app> via JavaScript.
The problem is that the newly injected HTML is not wired, as Angular goes through the compile and link phases only when the page is loaded the first time.
Is there a way to trigger them manually?
Am I approaching this problem in the wrong way? Is there a more idiomatic way to accomplish what I described?
Thanks
There are multiple ways to inject dynamic content into the view in AngularJS. One of the way to inject dynamic content is to use ng-include directive. It can take an endpoint from where to get view.
You can combine it with ng-if to achieve load view on click. For example:
<span ng-if="clicked">
<div ng-include='pathToTheHtml'></div>
</span>
The clicked variable would be false first, on clicking on the button set it to true, this would trigger ng-include to get the content and inject it into html.
If you want finer control then you need to use the $compile service. The html that needs to be injected into the DOM needs to be compiled and linked to the scope using $compile service. This can be done in a directive.
element.append($compile(htmlFragment)(scope))
angular.bootstrap(element, [modules], [config]);
Related
Before learning AngularJS I learned jQuery ( + mustache for templates). Now It is difficult to understand how to work with AngularJS...
I am trying to show modal window for user. Early (jQuery) I created a template, parsed it and appended it to the DOM.
In AngularJS, if I understand correctly, there are more than one way to do it. I can use ngView directive, ngInclude directive, ngBingHtml directive, create custom directive with 'templateUrl', and may be something else...
But I dont want to load templates from server on demand, I want to create script section with type='text/ng-template' and use it.
First of all I cant understand what the right way to choose, second is how dynamicly change templates (I need put template into directive, work with template, delete template, but not directive... yes?)
Thank a lot.
I am study the tutorial from code school, In the directive tutorial they are giving very simple example of custom directive like 1. Element Directive and 2. Attribute directive. So my question is we can achieve the requirement through the controller, then in which senario we will need custom directive.
Example Element directive
index.html
<product-title> </product-title>
Custom Directive
app.directive('productTitle', function(){
return {
restrict: 'E', // E for HTML Element
templateUrl: 'product-title.html'
};
});
product-title.html
<h3>
{{product.name}}
<em class="pull-right"> ${{product,price}}</em>
</h3>
Same thing can be do in controller
index.html
<div ng-controller="ctrl">
<h3> {{product.name}} </h3>
</div>
app.controller('ctrl', function(){
scope.product.name='HP';
})
Simple. Separation of concerns.
Controllers, architecturally aren't meant for HTML manipulation. They are meant for controlling data, stuff that is displayed on your view.
Whilst you are considering it simple to include that code in controller, which actually is, assume that tomorrow morning a change in the requirement forces you to alter the HTML. What follows is a heavy search and replace activity.
Directives generalize your HTML, they define a seperate layer where you can define custom tags and attributes that can simplify the view you're rendering. Stuffing everything in the controller, will slowly ugly out the whole code base, resulting in difficult code management.
By the way, I guess you'll soon stumble upon the fact that why should i use Services / Factories when i can achieve similar things using controllers. ?? You can check out this answer for more details
In this case the custom directives are mainly for the readability purposes. Custom directive allows you to wrap a chunk of HTML into a different file with a specific purpose. You could for example have a set up wizard for something on your web page. Each custom directive could then represent a separate step of your set up wizard. Instead of having a long HTML doc including all the steps.
You should always create a directive when you see a piece of code that can be reuse.. For example, a DatePicker would be created in a directive.. cause its gonna be useful in more than one place..
But even if its simple, all the logic will be at the same place and you can change it easily (only once) whenever you want. Besides, your source`ll turn more readable once you divide it in more pieces..
I'm working on a project with Yii2 and Angular. The structure of the code is as follows:
<html ng-app="myApp">
<head.../>
<body>
...
<div class="body-content"> MAIN CONTENT GOES HERE </div>
...
</body>
</html>
The page contains a header and a column on the left and a center area which is rendered inside the .body-content div. Now, as you can imagine, I have some buttons in there, some other angular widgets, etc..
Yii2 has a really cool feature called renderPartial that will re-render a view file without wrapping it again in the <head> and <body>. I use that to update the content of my main area, by calling that function, getting the response with jQuery and replacing the content.
Now, that causes all buttons that where binded with Angular to stop working (I'm guessing why). My question is: How can I make Angular re-run or re-bind all my (new) DOM elements to their actions?
You would have to use the manual bootstrap way (explained in https://docs.angularjs.org/guide/bootstrap) for angular but doing that would cause a memory leak over time as angular add listener on DOM that you destroy and is not aware of it's removal, so they stay, and so does for the controller / directives / binding and other features that are referenced by your code.
Is yii2 could be wrapped into an angular directive?
I am not sure if I am getting you right - you use a frontend framework AND a backend framework to control your frontend, the latter one deliveres new DOM content you inject into your HTML?
As far as I got it, Angular is best in handling everything while getting the data (be it from the backend in JSON or other format of your choice), NOT new DOM elements.
Angular itself binds to whatever DOM nodes it is added to, handles the content and dependency injection and thus displays your data. In your case the backend PHP framework seems to hand in new DOM elements that Angular thinks of "Hey - you don't want me to be adding them? fine, then I don't." and breaks.
Maybe there are solutions for this specific case, but if I were you I would rethink the concept in terms of "Where do I want my views/templates to be rendered? What part of the whole is responsible for what?" Using two different frameworks, let alone languages, to do the same job and interfering with one another would make a mess I wouldn't want to clean up.
So if you like this Yii2 feature and want to make it work, fine - but in that case - what do you need angular for? And if you'd rather stick to Angular you just have a backend that handles data and hands it back to the frontend to do it's job with it.
I'm building a third party widget that will be loaded onto multiple sites. I'm using angular for implementation, with a build script that wraps my angular so it doesn't interfere with any other angular that might be used on the page.
Everything works fine when I use my own custom directives, but when I tried to incorporate a loading indicator, using ng-show, it "sometimes" didn't work. I tracked the "sometimes" down to "on pages that already use angular".
It seems that the page's angular is still data binding my templates when they are inserted into the page. Is there any way I can make my dom a no-go zone for the page's angular?
ng-non-bindable seemed like it might work, but if I use that, I can't bootstrap underneath it.
What you need to do is to bootstrap angular programatically instead of using a tag.
<html>
<body>
// other parts of your site
<div></div>
// your angular stuff
<div id='app' ng-controller="MyController">
Hello {{greetMe}}!
</div>
</body>
</html>
// your controller
angular.module('myApp', [])
.controller('MyController', ['$scope', function ($scope) {
$scope.greetMe = 'World';
}]);
// bootstrap angular programatically/manually
angular.element('#id').ready(function() {
angular.bootstrap(angular.element('#id'), ['myApp']);
});
Without forgetting to use ng-non-bindable too on parts that u don't want to bind ofcoz
So, here is what I have done, which is an abomination. I would much prefer a clean answer, but this protects my dom from the other angular instance.
First, I wrap my entire dom element with ng-non-bindable. This keeps the page-level angular from interfering with it.
Then, I add the following, adapted from AngularJS - how to override directive ngClick
var root = angular.module('rootModule', []);
root.config(function($provide){
$provide.decorator('ngNonBindableDirective',
['$delegate', function($delegate){
$delegate.shift();
return $delegate;
}]);
});
This removes the implementation of ng-non-bindable inside my angular instance. So the page angular will ignore the dom, but my angular won't ignore it. I just hope I don't have to implement ng-non-bindable-really later down the line.
Someone please save me from this horror by giving me a clean answer!
my angular app is an html editor which sends the template to a server where it is rendered with dynamic data and returned to the client where it should be inserted into an iframe (for preview purpose). ng-bind-html seams not to work in combination with an iframe. is there a way to set the content of an iframe dynamically with angularjs?
edit:
the main problem of these templates is that they correspond to completly independent html documents (doctype, css, markup, etc.); hence it is necessary to encapsulate the rendered result within some kind of sandbox.
I don't know how to send content to iframe but you can use ng-include instead of iframe.
<div ng-include="frameUrl" ></div>