How to grab ng-binds output text from a directive? - javascript

In most of my application I'm using ng-bind to display the data in my application of curly interpolation {{ }} in my templates instead o. I attempted to grab the interpolated ng-bind value from my element, however I keep getting undefined. Here is a JSbin of my code (suggestion:open web dev console):
HTML:
<body ng-app="app">
<div ng-controller="controller as vm">
<section directit>
<p ng-bind="vm.value"></p>
</section>
</div>
</body>
JS:
angular.module('app', [])
.controller('controller', function(){
this.value = 'hello';
})
.directive('directit', function(){
return {
restrict: 'A',
link: function(scope,element,atts){
var p = element.children()[0];
console.log('pText',p.innerHTML); //undefined
console.log('p',[p]); //innerText value is defined upon inspection
}
}
});

Related

How to get the value of a custom attribute in angular js

I have created a custom attribute called test in angular js. When I write the test attribute just beside the ng-controller keyword i.d.
<div ng-controller="myCon" test="abc"></div> then I can access that test from the controller by using alert($attrs.test). But if I write the custom attribute test other than beside of the ng-controller keyword, I can't access that. i.e.
<div ng-controller="myCon">
<div test="def"></div>
</div>
In this case I got undefined in alert($attrs.test)
Full code...
<html>
<script src="angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="kumar" >
<button ng-click="check()" test="def">Click</button>
</div>
<script>
var app = angular.module("myApp", []);
app.directive("test", function() {
return {
//template : "<h1>Hello</h1>"
};
});
app.controller("kumar",function($scope,$attrs){
$scope.check=function(){
alert(JSON.stringify($attrs.test)); //getting undefined. I
//should get def.
}
});
</script>
</body>
</html>
app.directive("test", function() {
return {
restrict: "A",
scope: {
text: "#test"
}
};
});
Update your directive scope and add restrict . For better understanding refer to this question
You can check it:
<html>
<script src="src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js""></script>
<body ng-app="myApp">
<div ng-controller="kumar" >
<button ng-click="check()" test="def">Click</button>
</div>
<script>
var app = angular.module("myApp", []);
app.directive("test", function() {
return {
//template : "<h1>Hello</h1>"
};
});
app.controller("kumar",function($scope,$attrs){
$scope.check=function(){
var testa=$scope.test;
alert(JSON.stringify(testa)); //getting undefined. I
//should get def.
}
});
</script>
</body>
</html>
You can get the element on click if you pass $event in ng-click, i.e. ng-click="check($event)" and can get the attribute from $event.target.
Check fiddle : https://jsfiddle.net/ayusharma/xb63g9ca/
JS
app.controller('myCtrl', function($scope) {
$scope.clickMe = function(evt) {
console.log(evt.target.getAttribute('test'))
}
});
HTML
<div ng-controller="myCtrl">
<div ng-click="clickMe($event)" test="abc">Click on Me</div>
</div>

ng-init with condition statements

I have a Angular JS Application,
<div class="col-lg-12" ng-init="getTableData('{{URL::route('get_repair_category')}}')">
When Page loading the getTableData will execute, but I want to check a variable $rootScope.Dealer and switch the function name of initialization.
Eg : if $rootScope.Dealer value present I wanto execute the function named getDealerData
And If the value is not set need to execute the getTableData function.
How can I make this in anglar js template.
I just tried the ng-if, but its not working...
You can use simple Javascript syntax in ng-init directive like this:
<div class="col-lg-12" ng-init="Dealer ? getDealerData('{{URL::route('get_repair_category')}}') : getTableData('{{URL::route('get_repair_category')}}')">
Here is a plnkr for you (I've changed backend route generation to text):
https://plnkr.co/edit/CJOMT0g50BCWa3j02rcS?p=preview
Try this
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope, $rootScope) {
$rootScope.dealer = ["a", "b", "c"];
$scope.getTableData = function(x) {
return x;
}
$scope.getDelearData = function() {
return $rootScope.dealer;
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-init="data = getDelearData() || getTableData('table data')">
{{data}}
</div>
</div>

transclude usage in simple Directive Example

In the following simple example I am printing the name model from controller by directive on the view. The example is running fine, but what is the use of transclude I cannot understand. Can someone explain its usage?
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js" ></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<people></people>
<script>
//module declaration
var app = angular.module("myApp",[]);
//controller declaration
app.controller('myCtrl',function($scope){
$scope.name = "Peter";
});
//directives declaration
app.directive('people',function(){
return{
restric: 'E',
template: '<div>{{name}}</div>',
transclude: true
}
});
</script>
</body>
</html>
Your code doesn't really demonstrate what transclude does:
Look at this plunk and change the true/false value:
Plunk
You will notice the effect now hopefully. The source from plunkr, with a couple of modifications.
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#1.5.3" data-semver="1.5.3" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<people>HI there</people>
<script>
//module declaration
var app = angular.module("myApp",[]);
//controller declaration
app.controller('myCtrl',function($scope){
$scope.name = "Peter";
});
//directives declaration
app.directive('people',function(){
return{
restric: 'E',
template: '<div><ng-transclude></ng-transclude>: {{name}}</div>',
transclude: false
}
});
</script>
</body>
</html>
So when it is true, you will see that the contents are transcluded,
So it says HI There: Peter
When False, it removes the HI There, but keeps the name and my colon:
: Peter
Essentially, these are wrappers around any arbitrary content.
Supposing I have an accordion directive that shows or hides any content that you use it with with an animation.
app.directive('akordion', [function() {
return {
restrict: 'A',
replace: true,
transclude: true,
template: '<div class="accordion-wrapper">'
+'<div class="transcluded" ng-transclude></div>'
+'</div>',
link: function(scope, elem, attrs) {
scope.$watch(attrs.show, function(newVal){
toggle(newVal);
});
function toggle(show) {
var h = (show) ? 0 : '600px';
$(elem).css({ maxHeight: h });
}
}
}
}]);
You'd use it like this:
<div akordion="" id="league-admin">
<div>
foo
</div>
<my-directive></my-directive>
</div>
And the result (generated HTML) is:
<div class="accordion-wrapper" id="league-admin">
<div class="transcluded">
<div>
foo
</div>
<div id="my-directive">...</div>
</div>
</div>
The point is that by calling the akordion="", you take whatever is inside it and put it in the template (<div class="transcluded" ng-transclude>). In other words, the akordion directive wraps over (transcludes) the content you use it on.
Another example would be modal windows. You don't want to repeat the code that defines the modal each time you want to use it, so you define it once, and use transclusion to put any content into it. Check out modal in Bootstrap UI.
Basically If you have some content inside your directive it will be automatically replaced by the directive content
For Example, if you have<people>Test transclude</people> The Test transclude string will be automatically replace by angular when it process the directive. But what if you want 'Test transclude ' also to be displayed ? Here is where transclude come in to action.
Consider the following
app.directive('people',function(){
return{
restric: 'E',
template: '<div><div ng-transclude></div>{{name}}</div>',
transclude: true
}
});
Now the string 'Test transclude' will be also displayed inside tag
And this is the plunker link Plunk

Using ng-click inside a tooltip

I'm using Angular Bootstrap UI and I have a working tooltip.
HTML:
<div ng-app="helloApp">
<div ng-controller="helloCtrl as hello">
<a tooltip-trigger="click" tooltip-placement="bottom" uib-tooltip-html="<h1 ng-click='hello.clickInsideToSeeTheWorld()'>Click again!</h1>">Click me to see the tooltip</a>
</div>
</div>
Javascript:
angular.module('helloApp', ['ui.bootstrap'])
.controller('helloCtrl', helloCtrl)
function helloCtrl() {
var vm = this;
vm.clickInsideToSeeTheWorld = function() {alert(123)}
}
When I open up the tooltip, ng-click doesn't work. No alert appears. I receive no errors in my console. This is because the HTML isn't compiled. How can I properly compile the tooltip html to get this to work?
Extending the previous answer: You can probably use
uib-tooltip-template
instead of
uib-tooltip-html
when you exploit the angular template cache.
I understand that you maybe do not want to create an external template.html, but you do not have to do so. Simply try:
var app = angular.module("test", ['ui.bootstrap']);
app.controller("testController", function($scope, $templateCache) {
$scope.clickInsideToSeeTheWorld = function() {
alert(123)
}
if (!$templateCache.get ('template.html')) {
$templateCache.put (
'template.html',
'<a ng-click="clickInsideToSeeTheWorld()">Click again!</a>'
);
}
});
and
<div ng-app="test" ng-controller="testController">
<p style="margin-top: 5em;" uib-tooltip-template="'template.html'" tooltip-popup-close-delay="3000" >
Click me to see the tooltip
</p>
Here's an external plunker as well:
https://plnkr.co/edit/Dsi69MQg4NfgOSI5ClFh?p=preview
I added uib-tooltip-template instead uib-tooltip-html and changed this to $scope.
index.html
<body>
<script>
var app = angular.module("test", ['ui.bootstrap']);
app.controller("testController", function($scope) {
$scope.clickInsideToSeeTheWorld = function() {
alert(123)}
});
</script>
<div ng-app="test" ng-controller="testController">
<p style="margin-top: 5em;" uib-tooltip-template="'template.html'" tooltip-popup-close-delay="3000" >
Click me to see the tooltip
</p>
</div>
</body>
template.html
<a ng-click="clickInsideToSeeTheWorld()">Click again!</a>
Here is working Plunker
Or Alternative solution is for you to compile code yourself and then assign it to tooltip html
var sc = scope.$new( true ); //scope for html
sc.hello = {} // assign your hallo object to new scope
var compiledHtml = $compile( '<h1 ng-click="hello.clickInsideToSeeTheWorld()">Click again!</h1>')( sc );
Then you can set tooltip html to compiledHtml.

How to render HTML Tags from ngModel?

I'm using AngularJS for binding JS variables to my HTML content, and it works fine.
JS
var app = angular.module("Tabs", [])
.controller("TabsController", ['$scope', function($scope){
$scope.events = my_JS_object;
})
HTML
<div>{{events.test}}</div>
It works as long as my_JS_object.test is a simple string, like "Hello World", but once I try to put HTML tag in there, such as Hello <b>World</b> It doesn't use the tags as HTML elements, but as simple text. Which makes sense, only I have no idea how to make the HTML tags work.
As stated by Angular documentation, you can use inbuilt ng-bind-html directive to evaluate model string and insert resulting HTML into element.
Example:
If you have model value like:
$scope.myHTML =
'I am an <code>HTML</code>string with ' +
'links! and other <em>stuff</em>';
Use ng-bind-html like:
<p ng-bind-html="myHTML"></p>
For detailed information go through: https://docs.angularjs.org/api/ng/directive/ngBindHtml
Note: Don't forget to inject ngSanitize service in your app.
You need to use the ngBindHtml directive that properly evaluates the expression and inserts the resulting HTML into the element in a secure way. To do this, you must include a reference to angular-sanitize.js in your HTML and then in your angular module, inject ngSanitize.
Like so
var app = angular.module("Tabs", ['ngSanitize'])
.controller("TabsController", ['$scope', function($scope){
$scope.events = my_JS_object;
})
<div ng-controller="TabsController">
<div ng-bind-html="events.test"></div>
</div>
Here is a full working example:
(function(angular) {
'use strict';
angular.module('bindHtmlExample', ['ngSanitize'])
.controller('ExampleController', ['$scope', function($scope) {
$scope.myHTML = 'Hello This is <b>BOLD<b/>';
}]);
})(window.angular);
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular-sanitize.js"></script>
</head>
<body ng-app="bindHtmlExample">
<div ng-controller="ExampleController">
<p ng-bind-html="myHTML"></p>
</div>
</body>
Refer to the official angular documentation for details:
https://docs.angularjs.org/api/ng/directive/ngBindHtml
If you want to insert HTML into page you shouldn't do it this way.
There is sanitize for this task.
For example in your controller:
$scope.trustedHtml = "<b>Hello World</b>"
And in your html:
<div ng-bind-html="trustedHtml "></div>
Always check html if using a user given text before inserting.
Also don't forget to add ngSanitize as dependency while creating controller
It's easier to use transclusion if you want to embed custom HTML into your DOM tree.
angular.module('myApp', [])
.controller('MainCtrl', function ($scope) {
$scope.overwrite = false;
$scope.origin = 'parent controller';
})
.directive('myDirective', function() {
return {
restrict: 'E',
templateUrl: 'my-directive.html',
scope: {},
transclude: true,
link: function (scope) {
scope.overwrite = !!scope.origin;
scope.origin = 'link function';
}
};
});
<script src="https://code.angularjs.org/1.3.2/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MainCtrl">
<my-directive>
<p>HTML template</p>
<p>Scope from {{origin}}</p>
<p>Overwritten? {{overwrite}}</p>
</my-directive>
</div>
<script type="text/ng-template" id="my-directive.html">
<ng-transclude></ng-transclude>
<hr />
<p>Directive template</p>
<p>Scope from {{origin}}</p>
<p>Overwritten? {{overwrite}}</p>
</script>
</div>

Categories

Resources