Understanding the contextual usage of scope in angular directive - angularjs

I was just going through the documentation of Angular.js for ngTransclude, i came across the following example:
<script>
angular.module('transcludeExample', [])
.directive('pane', function(){
return {
restrict: 'E',
transclude: true,
scope: { title:'#' },
template: '<div style="border: 1px solid black;">' +
'<div style="background-color: gray">{{title}}</div>' +
'<ng-transclude></ng-transclude>' +
'</div>'
};
})
.controller('ExampleController', ['$scope', function($scope) {
$scope.title = 'Lorem Ipsum';
$scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
}]);
</script>
<div ng-controller="ExampleController">
<input ng-model="title" aria-label="title"> <br/>
<textarea ng-model="text" aria-label="text"></textarea> <br/>
<pane title="{{title}}">{{text}}</pane>
</div>
I am not quite sure why these two properties are used in the directive:
transclude: true,
scope: { title:'#' },
I beleive doing transclude: true, gives the directive access to
$scope.title
$scope.text
which is in the controller , i am not sure about this though , but why is scope being used here ? i mean in such a weird fashion that too, I.E. ,
scope: { title:'#' },
What is the # there for ? so to sum up my whole question, can somebody explain to me why the transclude and scope properties are used here in the directive ?
Thank you

The transclude property tells angular to replace the <ng-transclude> tag with the HTML code inside the directive. In your case, the {{text}} string.
The property:
scope: { title:'#' },
tells angular to include the attribute title passed to the directive in its scope.
More documentation here:
What is the difference between '#' and '=' in directive scope in AngularJS?
and of course here:
https://docs.angularjs.org/guide/directive

Related

Using template from 1 directive into another directives template

Basically I have 2 custom directives, each having it's own template. What I need is to insert one of the templates into the other. I have also read about transclusion, but can't wrap my head around it. Any ideas would be of great help!
From the AngularJS Website, an example:
<script>
angular.module('transcludeExample', [])
.directive('pane', function(){
return {
restrict: 'E',
transclude: true,
scope: { title:'#' },
template: '<div style="border: 1px solid black;">' +
'<div style="background-color: gray">{{title}}</div>' +
'<ng-transclude></ng-transclude>' +
'</div>'
};
})
.controller('ExampleController', ['$scope', function($scope) {
$scope.title = 'Lorem Ipsum';
$scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
}]);
</script>
<div ng-controller="ExampleController">
<input ng-model="title" aria-label="title"> <br/>
<textarea ng-model="text" aria-label="text"></textarea> <br/>
<pane title="{{title}}"><span>{{text}}</span></pane>
</div>
You have to create the custom directive, in this case "pane", from inside angular.module. When you have done that, the directive exists from within the module which should be your application and you can use it freely as it is returned from the directive example. In this case the example uses the "pane" directive and it associates the transcluded template to it.

angular bind html tags from controller to html view

I need to render the $scope.htmlView tags in to html view.
I already tried using ng-bind-html. It renders the html tags but scope variable values will not appear.
How can I render both html tags and and scope variable values?
This is the controller:
$scope.newObj = {
billStatus : true;
eventTime : "2015-01-10"
};
$scope.htmlView = '<p>{{newObj.eventTime}}</p> <div style="margin-top: -15px;"><md-checkbox ng-checked="{{newObj.billStatus}}" style="margin-left: 0px;" aria-label="Bilable"><span style="margin-left:0px;">Bilable</span> </md-checkbox></div>'
Expected result is:
<p> 2015-01-10</p>
<div style="margin-top: -15px;">
<md-checkbox ng-checked="true" style="margin-left: 0px;" aria- label="Bilable">
<span style="margin-left:0px;">Bilable</span>
</md-checkbox>
</div>
I search over the internet over days and still could't find out a way to figure out this. please help me. thank you.
You have to do 2 things.
Use data-ng-bind-html=""
Use $sce.trustAsHtml(string)
UPDATED:
If you wont to use angular expressions, you have to compile them using
$compile.
You can read more via this $SCE
I will tell you a long way but it will help you.Make a custom directive like this.
app.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.dynamic, function(html) {
ele.html(html);
$compile(ele.contents())(scope);
});
}
};
});
Use as
<span dynamic="{{htmlView}}" >
Hi please check this fiddle
https://plnkr.co/edit/iqNltdDYv2n9Agke0C2C?p=preview
HTML
<div ng-controller="ExampleController">
<p >{{newObj.eventTime}}</p>
<p dynamic="htmlView"></p>
</div
and JS
(function(angular) {
'use strict';
angular.module('bindHtmlExample', ['ngSanitize'])
.controller('ExampleController', ['$scope', function($scope) {
$scope.newObj = {
billStatus : true,
eventTime : "2015-01-10"
}
$scope.htmlView = '<p> {{newObj.eventTime}}</p> <div style="margin-top: -15px;">Hello <md-checkbox ng-checked="{{newObj.billStatus}}" style="margin-left: 0px;" aria-label="Bilable"><span style="margin-left:0px;">Bilable</span> </md-checkbox></div>'
}])
.directive('dynamic', function($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, element, attrs) {
scope.$watch(attrs.dynamic, function(html) {
element[0].innerHTML = html;
$compile(element.contents())(scope);
});
}
};
});
})(window.angular);

Angular Custom Directive Does not trigger ng-click

I have a directive which populates content using ng-repeat. I have an ng-click / ng-focus event on each element inside but the click does not trigger the action.
This works when I remov the ng-repeat from the template. I'm using angularjs 1.3.4
app.directive('inputTable', [function(){
restrict: 'E',
template: '<div ng-repeat="item in items" >
<div >
<input type="text" ng-focus="focusTap()" ng-model="item.name" placeholder="Name">
</div>
</div>',
replace:true,
scope: {
items:'=items'
},
controller:['$scope', '$element', function($scope, $element ){
$scope.focusTap = function(){
console.log('focus called');
}
}],
link: ['$scope', '$element', 'attributes', function($scope, $element, attributes){
}],
}]
Seems to be a bug. Works as expected in 1.3.0-beta.10, but not later versions.
If using a newer version then remove replace: true and it will work.
Demo: http://plnkr.co/edit/hb5eWfoYH4PCkNaYaxn6?p=preview

Ng-transclude with nested directives

I am working with 2 directives where one directives template contains the second directive. I would like to use ng-transclude inside the second (nested) directive. How can I accomplish this? Here is a plnkr.
<body ng-app="transcludeExample">
<script>
angular.module('transcludeExample', [])
.directive('pane', function(){
return {
restrict: 'E',
transclude: true,
scope: { title:'#' },
template: '<div style="border: 1px solid black;">' +
'<div style="background-color: yellow">{{title}}</div>' +
'<test></test>' +
//'<ng-transclude></ng-transclude>' +
'</div>'
};
})
.directive('test', function(){
return {
restrict: 'E',
transclude: true,
template: '<div><ng-transclude></ng-transclude></div>'
};
})
.controller('ExampleController', ['$scope', function($scope) {
$scope.title = 'Lorem Ipsuma';
$scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
}]);
</script>
<div ng-controller="ExampleController">
<input ng-model="title"> <br/>
<textarea ng-model="text"></textarea> <br/><br/><br/><br/><br/><br/>
<pane title="{{title}}">{{text}}</pane>
</div>
</body>
Don't know if I'm missing something, but this seems to work:
template: '<div style="border: 1px solid black;">' +
'<div style="background-color: yellow">{{title}}</div>' +
'<test><ng-transclude></ng-transclude></test>' +
'</div>'

Using ng-switch in directive with transclude

I am trying to create a template that shows some transcluded content. When I use ng-show everything works fine, but using ng-if or ng-switch gives me problems. I get this error message: Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found
I understand that ng-switch creates a new scope. But the transclude should still go up to the parent chain. Is this a defect in angularjs? See http://jsfiddle.net/HgvP7/
Here is my html, modified from the documentation example:
<div ng-app="docsTransclusionExample">
<div ng-controller="Ctrl">
<my-dialog>Check out the contents, {{name}}!</my-dialog>
</div>
<!-- my-dialog.html -->
<script type="text/ng-template" id="my-dialog.html">
<div ng-switch="1+1">
<div ng-switch-when="2">
<div ng-transclude></div>
</div>
</div>
</script>
</div>
And the code:
angular.module('docsTransclusionExample', [])
.controller('Ctrl', function($scope) {
$scope.name = 'Tobias';
})
.directive('myDialog', function() {
return {
restrict: 'E',
transclude: true,
scope: {},
templateUrl: 'my-dialog.html',
link: function (scope, element) {
scope.name = 'Jeff';
}
};
});

Resources