I'm trying to render html content from a controller , but the angular directive ng-hide doesn't work , I've tried the following code, does it have a problem with binding as html this way?
var htmlContent = "<Div class='vzone' ng-hide='true' id='parent_" + ViewerZones[CurrentIndex].Id + "'...'></div>";
$scope.PageContent = $sce.trustAsHtml(htmlContent);
<div ng-bind-html="PageContent"></div>
try this one,
var htmlContent = "<Div class='vzone' ng-.....
$scope.PageContent = $sce.trustAsHtml($compile(htmlContent));
don't forget to add $compile dependency in your controller.
$compile service will bind your dynamic directives with the controller
Related
I am trying to write a functionality where if we pass the scope and template, it should show the given template in a jQuery UI dialog with the all working bindings from the given scope.
Here is the code:
HTML
<div id="mainDiv" ng-controller="myCtrl">
<input type="button" value="show dialog" ng-click="showTemplateDialog()" />
</div>
<script type="text/ng-template" id="dialogTemplate">
<div>
This is template div.
<span>Message: </span>
<p>{{message}}</p>
</div>
</script>
JS
var app = angular.module('myApp', []).controller('myCtrl', function($scope, $compile) {
$scope.showTemplateDialog = function() {
alert("hi")
var newScope = $scope.$new();
newScope.message = "This is some message";
$scope.showDialog(newScope, "dialogTemplate")
};
$scope.showDialog = function(dialogScope, template) {
var div = $("<div style='' id='dialog' title='Test Dialog' ng-include=\"'" + template + "'\"></div>");
$compile(div)(dialogScope);
$("#mainDiv").append(div);
div.dialog();
}
})
The problem is when I call div.dialog(), it throws following error in jquery-ui.min.js
Unhandled exception at line 9, column 26027 in http://localhost/TestApp/scripts/jquery-ui.min.js
0x800a138f - JavaScript runtime error: Unable to get property 'display' of undefined or null reference
Please suggest some way to resolve this error. Or suggest some other way to show and html/template in jQuery dialog using angularjs.
I think the value of div would be a JQuery object. I would try passing the HTML string directly to compile(). The result of compile(html)(scope) is an array IIRC, so you probably want to append its first element [0].
EDIT: I just tried that and it seems Angular won't allow ng-include being compiled this way.
I just tried what Hubert suggested, but still it was not working. Then I realize when I am creating the div, it's not properly getting created and was showing localName of the html element as null.
Then I did some changes in my code and it worked. I just added another div inside the div I was creating and put ng-include on that.
Here is the updated code:
$scope.showDialog = function(dialogScope, template) {
var div = $("<div id='dialog' title='Test Dialog' ><div ng-include=\"'" + template + "'\"></div></div>");
$compile(div)(dialogScope);
$("#mainDiv").append(div);
div.dialog();
}
I am wondering if I can make an Angular Js directive then I can use it again on the run time
here is a simple example
app.directive('w34Directive',function(){
return{
template : "<p>test</p>"
}
})
and here is the HTML
<div w34-directive></div>
but if I have a button with ng-click function that do the following function in the controller
var elem = document.querySelector('.myContainer');
angular.element(elem).append("<div w34-directive></div>");
which mean that a new DOM uses the directive will be generated but actually the angular directives fire once on the page load so when I add the new DOM it just add an empty div tag without the template of the directive which is in this case :
<p>test</p>
any idea about how to overcome this ?
Yes, you can do it using :
$compile
Exemple :
var el = $compile( "<div w34-directive></div>" )( $scope );
angular.element(elem).append( el );
I would like to interact with a scoped inside an appended html element on the page, can someone please show me how to update that scope?
var overlay = angular.element('<div id="flyout-overlay" class="page-overlay global" ng-show="testScope"></div>');
mainContent.append(overlay);
$timeout(function(){
$scope.testScope = true; // how?
},500);
use $compile service
$compile(overlay);
here is the documentation
don't forget to add $compile dependency in the controller
doc says,
apply to your case,
'<div id="flyout-overlay" class="page-overlay global" ng-show="testScope"></div>'
1 : compile - $compile collect all the directives, for ex, it will collect ng-show directive
2: link - combine the directive with a scope.. , for ex, it will bind the ng-show="testScope" directive with the scope.
#Kalhano gave the perfect answer but since you don't know about the $compile service, here is the code for you. Just a small change....
var overlayTmpl = angular.element('<div id="flyout-overlay" class="page-overlay global" ng-show="testScope"></div>');
var overlay = $compile(overlayTmpl)($scope);
mainContent.append(overlay);
$timeout(function(){
$scope.testScope = true; // how?
},500);
in nutshell, $compile service compiles your html and links it to the scope you provided,
for better understanding read the angular documentation.
Question
In AngularJS, is there a way to convert a string template into markup without using scope or a directive?
Explanation
I have a service which allows me to create new angular apps dynamically. It builds up the DOM for the new app, then runs angular.boostrap on the element.
Currently, the DOM is created like this:
var element = document.createElement('div');
element.setAttribute('app', '');
element.setAttribute('size', 'small');
...
element.className = 'app layout--relative';
There are many attributes, classes, child elements, etc, so creating the markup in this way is not ideal. It would be better to use a template.
Normally I would use $compile to convert a string template into markup, but because I have not run angular.bootstrap yet, there is no scope in order to use $compile(template)(scope);
What I have tried
Create a div, then replace the innerHTML with the template string
This works, but all of the attributes and classes on the root element need to be added separately.
var element = document.createElement('div');
element.innerHTML = template;
Remove scope after the template has compiled
This works, but I would prefer to avoid scope altogether:
var scope = $rootScope.$new();
var element = $compile(template)(scope);
scope.$destroy();
You could use the $interpolate service for string substitution like this:
var template = '<div app size="{{size}}" class="{{className}}">' +
'<span>Hello {{name}}!</span>' +
'</div>';
$interpolate(template)({
size: 'small',
className: 'app layout--relative',
name: 'World'
});
and the result would be like this:
<div app size="small" class="app layout--relative">
<span>Hello World!</span>
</div>
Hope this helps.
So I have some html that gets loaded into the #panel div dynamically depending on which questionNumber the user is on. This is not all of the code but all of the relevant code I think. Anyway, the <input> get's loaded into the page but it doesn't actually do anything. what am I missing here? I have the same problem when the questionNumber === 1, where the binded variables just show up as {{variable}} etc
var readingController = function (scope, Romanize){
scope.usersRomanization;
//alert(scope.usersRomanization);
}
var app = angular.module('Tutorials', ['functions', 'tutorials']).controller('getAnswers', function ($scope, $element, Position, Romanize) {
$scope.sectionNumber = Position.sectionNumber;
if ($scope.sectionNumber === 0){
$('#panel').html('<div ng-controller="readingController"><input ng-model="usersRomanization"></input></div>');
readingController($scope, Romanize);
}
<body ng-controller="getAnswers">
<div id="panel">
</div>
</body>
If you add HTML to the DOM, you have to tell Angular to $compile it. This should be done in a directive. You'll need to inject $compile then do something like this:
var content = '<div ng-controller=...></div>';
var compiled = $compile(content)(scope);
// then put the content where you want
Or better, define a directive and use a template, which will automatically get compiled for you by Angular.
Other alternatives are ng-include (which will compile the loaded content for you) and ng-switch, which would allow you to put the templates into the HTML.