I'm trying to compile a template which has data-ng-include and data-ng-src defined. I'm trying to set the src by calling getPartial(), which returns the path of the template. But the getPartial() is not getting called.
HTML:
<button ng-click="displayElements();">Display Elements</button>
<div id="container"></div>
JS:
$scope.displayElements = function() {
var template = '<div data-ng-include data-ng-src="getPartial()"></div>';
var linkFn = $compile(template)($scope);
//console.log(angular.element(document.getElementById("container")));
angular.element(document.getElementById("container")).append(linkFn);
}
$scope.getPartial = function() {
console.log("from partial");
return 'hello.html';
}
Plnkr : http://plnkr.co/edit/ig9TAXVpK4k1bQwi9PQo?p=preview
ng-include uses either its own value or value of src attribute to get the path (see documentation). You're trying to use ng-src, which is a directive in its own right. So you need to do either this:
<div data-ng-include="getPartial()"></div>
or this:
<div data-ng-include data-src="getPartial()"></div>
On a sidenote, watching a function call result hurts performance. You'd be better served by putting the resolved source path into a scope variable.
Here is the solution:-
var app = angular.module('plunker', []);
app.controller('MainCtrl', ['$scope', '$compile', function($scope, $compile) {
$scope.displayElements = function() {
var template = '<div data-ng-include data-ng-init="getPartial()" src="htmlToLoad"></div>';
var linkFn = $compile(template)($scope);
angular.element(document.getElementById("container")).append(linkFn);
};
$scope.getPartial = function() {
alert("from partial");
$scope.htmlToLoad = 'hello.html';
};
}]);
http://plnkr.co/edit/y3PgeBMVHytftI7NDSq4?p=preview
'<div data-ng-include data-ng-src="getPartial()"></div>';
replace your code with this
'<div data-ng-include data-ng-init="getPartial()" src="htmlToLoad"></div>';
var app = angular.module('plunker', []);
app.controller('MainCtrl', ['$scope', '$compile', function($scope, $compile) {
$scope.displayElements = function() {
var template = '<div data-ng-include data-ng-init="getPartial()" src="htmlToLoad"></div>';
var linkFn = $compile(template)($scope);
//console.log(angular.element(document.getElementById("container")));
angular.element(document.getElementById("container")).append(linkFn);
}
$scope.getPartial = function() {
alert("sdfsdfsdf");
console.log("from partial");
return 'hello.html';
}
}]);
Related
Here is my Markup
<div ng-app="myApp" ng-controller="myCtrl">
<input type="text" ng-model="name">
<p ng-bind-html="myText|unsafe"></p>
</div>
I am using this code
var app = angular.module("myApp", ['ngSanitize']);
app.controller("myCtrl", function($scope) {
$scope.myText = "My name is: <h1>{{name}}</h1>";
$scope.name="Habib";
});
app.filter('unsafe', function ($sce) {
return function(val) {
return $sce.trustAsHtml(val);
};
});
Output:
My name is: {{}}
Desired Output:
My name is: Habib
I want it should also reflect value from textbox.
EDIT
The reason you are having issues with getting $scope.name bound is because ng-bind-html does not bind that html to the current scope. You can use a directive to fix this. Here is an answer that fixes your issue.
Here is a plunker that adds the directive and shows the behavior you are looking for.
Here is the directive that was added that fixes your issue:
app.directive('compileTemplate', function($compile, $parse){
return {
link: function(scope, element, attr){
var parsed = $parse(attr.ngBindHtml);
function getStringValue() {
return (parsed(scope) || '').toString();
}
// Recompile if the template changes
scope.$watch(getStringValue, function() {
// The -9999 makes it skip directives
// so that we do not recompile ourselves
$compile(element, null, -9999)(scope);
});
}
}
});
You need to declare $scope.name="Habib" before the myText scope variable.
var app = angular.module("myApp", ['ngSanitize']);
app.controller("myCtrl", function($scope) {
$scope.name="Habib";
$scope.myText = "My name is: <h1>{{name}}</h1>";
});
app.filter('unsafe', function ($sce) {
return function(val) {
return $sce.trustAsHtml(val);
};
});
Ho can I get the window width in angularJS on resize from a controller? I want to be able to get it so I can display some div with <div ng-if="windowWidth > 320">
I can get the windowWidth on the initial page load but not on resize...
'use strict';
var app = angular.module('app', []);
app.controller('mainController', ['$window', '$scope', function($window, $scope){
var mainCtrl = this;
mainCtrl.test = 'testing mainController';
// Method suggested in #Baconbeastnz's answer
$(window).resize(function() {
$scope.$apply(function() {
$scope.windowWidth = $( window ).width();
});
});
/* this produces the following error
/* Uncaught TypeError: mainCtrl.$digest is not a function(…)
angular.element($window).bind('resize', function(){
mainCtrl.windowWidth = $window.innerWidth;
// manuall $digest required as resize event
// is outside of angular
mainCtrl.$digest();
});
*/
}]);
// Trying Directive method as suggested in #Yaser Adel Mehraban answer.
/*app.directive('myDirective', ['$window', function ($window) {
return {
link: link,
restrict: 'E'
};
function link(scope, element, attrs){
angular.element($window).bind('resize', function(){
scope.windowWidth = $window.innerWidth;
});
}
}]);*/
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<body ng-app="app" ng-controller="mainController as mainCtrl">
<p>{{mainCtrl.test}}</p>
<hr />
<p ng-if="windowWidth > 600">The window width is {{windowWidth}}</p>
<div my-directive ng-if="windowWidth > 320">It works!</div>
</body>
I see in this answer they explain how you can get it from within a directive but how can you get it to work from within a controller?
The best way is to use a directive and watch for resize event of the window:
'use strict';
var app = angular.module('plunker', []);
app.directive('myDirective', ['$window', function ($window) {
return {
link: link,
restrict: 'A'
};
function link(scope, element, attrs){
angular.element($window).bind('resize', function(){
scope.windowWidth = $window.innerWidth;
});
}
}]);
And use it on your div:
<div my-directive ng-if="windowWidth > 320">
Here is a working plunker.
Finnally got it working with the below. Took most of the code from https://stackoverflow.com/a/23078185/1814446.
The only difference was for the ng-if to work the directive had to be put on a parent html element.
'use strict';
var app = angular.module('app', []);
app.controller('mainController', ['$window', '$scope', function($window, $scope){
var mainCtrl = this;
mainCtrl.test = 'testing mainController';
}]);
app.directive('windowSize', function ($window) {
return function (scope, element) {
var w = angular.element($window);
scope.getWindowDimensions = function () {
return {
'h': w.height(),
'w': w.width()
};
};
scope.$watch(scope.getWindowDimensions, function (newValue, oldValue) {
scope.windowHeight = newValue.h;
scope.windowWidth = newValue.w;
scope.style = function () {
return {
'height': (newValue.h - 100) + 'px',
'width': (newValue.w - 100) + 'px'
};
};
}, true);
w.bind('resize', function () {
scope.$apply();
});
}
})
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<body window-size my-directive ng-app="app" ng-controller="mainController as mainCtrl">
<p>{{mainCtrl.test}}</p>
<hr />
<div ng-if="windowWidth > 500">
<h4 style="margin:5px 0">It works!</h4>
<p style="margin:0">window.height: {{windowHeight}}</p> <p style="margin:0">window.width: {{windowWidth}}</p> <p style="margin:0">{{mainCtrl.test}}</p>
</div>
</body>
Getting the window width on resize isn't anything specific to Angular JS. in fact Angular doesn't provide any capability to do it. It's native javascript, the native window object fires a resize event that you can access. jQuery provides a handy wrapper for this. By using a simple callback in your controller and then updating your double bound windowWidth property on the $scope object you can get the functionality you need without using a directive.
$(window).resize(function() {
$scope.windowWidth = $( window ).width();
});
Just include this code in your controller and you will get the new window width every time.
$scope.windowWidth = $window.innerWidth;
angular.element($window).bind('resize', function(){
$scope.windowWidth = $window.innerWidth;
$scope.$apply();
});
I have an angularjs sample code snippet here where i can bind the html tags using ng-bind-html directive. But how can I include some other tags like angularjs ng-click, id tag etc inside ngBindHtml directive like
Test
My sample code is here:
var app = angular.module("myApp", ['ngSanitize']);
app.controller("myCtrl", function($scope) {
$scope.myText = "<a href='#' ng-click='someFunction()'>Test</a>";
$scope.someFunction = function(){
alert("Link Clicked");
};
});
FYI, the data is loaded dynamically from server side script and i have to use ng-bind-html inside ng-repeat directive and i have to pass respective id's to click events something like ng-click="myFunction(x.id)" as in sample 2.
As suggested #Dr Jones, you need use $compile directive.
Live example on jsfiddle.
angular.module('ExampleApp', [])
.controller('ExampleController', function($scope) {
$scope.myText = "<button ng-click='someFunction(1)'>{{text}}</button>";
$scope.text = "Test";
$scope.someFunction = function(val) {
console.log(val);
};
})
.directive('bindHtmlCompile', function($compile) {
return {
restrict: "A",
scope: {
bindHtmlCompile: "="
},
link: function(scope, elem) {
scope.$watch("bindHtmlCompile", function(newVal) {
elem.html('');
var newElem = angular.element(newVal);
var compileNewElem = $compile(newElem)(scope.$parent);
elem.append(compileNewElem);
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="ExampleApp">
<div ng-controller="ExampleController">
<h3>
Write code for test button
</h3>
<textarea cols="100" ng-model="myText"></textarea>
<div bind-html-compile="myText">
</div>
</div>
</div>
I am new to angularjs ,building my first angular app now i want to display the data which i displayed right now in a table using a customized directive.
can anyone tell me how can i do this?
i just want to have a custom directive and all data should be displayed using that directive.
is customized directive should placed in a separate file?
please guide me how can i do it?
here is my controller:
'use strict';
app.controller('myAppCtrl', function ($scope, $http) {
$scope.names = []
$http.get('https://www.reddit.com/r/worldnews/new.json')
.success(function (response) {
$scope.names = response.data.children;
})
});
https://jsfiddle.net/rr6q0umb/4/
You should go through some resources online to study about angular directives .
https://docs.angularjs.org/guide/directive
http://www.tutorialspoint.com/angularjs/angularjs_custom_directives.htm
Simple directive approach for beginners
//Controller
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
});
//Directive
app.directive('simpleDemo',function(){
var newtemplate = function(){
var template = '<i class="glyphicon glyphicon-remove"><i>';
return template;
}
return {
restrict: 'E',
template: newtemplate
}
})
//html
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<button><simple-demo></simple-demo></button>
It might help you!
<html>
<head>
<title>Angular JS Custom Directives</title>
</head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
var mainApp = angular.module("mainApp", []);
mainApp.directive('student', function() {
var directive = {};
directive.restrict = 'E';
directive.template = "Student: <b>{{student.name}}</b> , Roll No: <b>{{student.rollno}}</b>";
directive.scope = {
student : "=name"
}
directive.compile = function(element, attributes) {
element.css("border", "1px solid #cccccc");
var linkFunction = function($scope, element, attributes) {
element.html("Student: <b>"+$scope.student.name +"</b> , Roll No: <b>"+$scope.student.rollno+"</b><br/>");
element.css("background-color", "#ff00ff");
}
return linkFunction;
}
return directive;
});
mainApp.controller('StudentController', function($scope) {
$scope.Mahesh = {};
$scope.Mahesh.name = "Mahesh Parashar";
$scope.Mahesh.rollno = 1;
$scope.Piyush = {};
$scope.Piyush.name = "Piyush Parashar";
$scope.Piyush.rollno = 2;
});
</script>
<body>
<h2>AngularJS Sample Application</h2>
<div ng-app="mainApp" ng-controller="StudentController">
<student name="Mahesh"></student><br/>
<student name="Piyush"></student>
</div>
</body>
</html>
Reference URLs:
https://www.airpair.com/angularjs/posts/creating-components-p3-angular2-directives
http://tutorials.jenkov.com/angularjs/custom-directives.html
http://www.sitepoint.com/practical-guide-angularjs-directives/
I am facing a small problem during the compilation of html code in angularjs. Here is the brief description of my problem :
$scope.report= reportdata;
reportdata is the html code that contains angularcontents like : {{name}} , {{firstname}} etc.
so, I am searching for a function that can compile the above html in my controller just like this :
$scope.compiledReportdata = function() {
$scope.compildeHtml = somefunction(reportdata);
}
Is there any function that can do the trick for me , Please suggest.
This is what i have tried i works for HTML but not for Controller
angular.module('myapp')
.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
ele.bind('blur', function () {
scope.$apply(attrs.uiBlur);
debugger
});
scope.$watch(attrs.dynamic, function (html) {
ele.html(html);
var data1 = ele.html(html);
var data2 = $compile(ele.contents())(scope);
$compile(ele.contents())(scope);
});
}
};
});
You can use the $interpolate service in the controller to interpolate the string...
var app = angular.module('app', ['ngSanitize']);
app.controller('controller', function ($scope, $interpolate) {
$scope.name = 'Costanza';
$scope.firstname = 'George';
$scope.report = '<strong>{{name}}</strong> , {{firstname}}';
$scope.compiledReportdata = function () {
return $interpolate($scope.report)($scope);
};
});
And you can use ngBindHtml with ngSanitize to display it...
<div ng-app="app" ng-controller="controller">
<div ng-bind-html="compiledReportdata()"></div>
</div>
JSFiddle