why ng-transclude not working in angular js as expected - angularjs

I make a simple directed with isolated scope .I read the tutorial of transclude but when I apply it not working as expected .I need to show "dd" and test together how I can show this
here is my plunker
http://plnkr.co/edit/OxmVga7DdkNxzPnfDtGS?p=preview
var app =angular.module('app',[]);
app.directive('newdir',function(){
return {
restrict:"E",
scope:{
fr:'#'
},
replace:true,
transclude: true, // we want to insert custom content inside the directive
template:"<div ng-transclude >{{fr}}</div>"
}
});

The transcluded element gets completely replaced. Replace your template with this to see what is happening:
<div><h3>BEFORE</h3><h1 ng-transclude>MISSING</h1><h3>AFTER</h3>{{fr}}</div>

Related

Run 'ng-click' inside a directive's isolated scope

Thanks in advance for taking the time to look into this question
I have serverside generated code that renders a directive wrapped around pre-rendered content.
<serverside-demo color="blue">
<p><strong>Content from Server, wrapped in a directive.</strong></p>
<p>I want this color to show: <span ng-style="{color: color}">{{color}}</span></p>
<button ng-click="onClickButtonInDirective()">Click Me</button>
</serverside-demo>
This means that 1.) the directive tag, 2.) the content inside the directive tag, 3.)the ng-click and 4.) The curly braces syntax are all generated by the server.
I want AngularJs to pick up the generated code, recompile the template and deal with the scope.
The problem is that I am having trouble getting it working. I understand that because the ng-click is inside the controller block, it is picked up not by the directive isolated scope, but the parent controllers. Instead I want the opposite... to pick up the onClickButtonInDirective scope function inside the serversideDemo link
I have created a jsfiddle best explaining my problem, which aims to clearly demonstrate the working "traditional" way of loading the template separately (which works) comparing it to the server-side way.
https://jsfiddle.net/stevewbrown/beLccjd2/3/
What is the best way to do this?
Thank you!
There are two major problem in your code
1- directive name and dom element not matched, - missing in dom element
app.directive('serverSideDemo', function() {
use <server-side-demo color="blue"> instead of <serverside-demo color="blue">
2- you need to compile the html code of server-side-demo dom with directive scope in link function
$compile(element.contents())(scope);
Working jsfiddle
Use templateUrl instead of template to fetch the content of directive from server:
app.directive('serverSideDemo', function() {
return {
restrict: 'AE',
scope: {
color: '='
},
templateUrl: 'link/that/returns/html/content',
link: function(scope, element, attrs) {
scope.onClickButtonInDirective = function() {
console.log('You clicked the button in the serverside demo')
scope.color = scope.color === 'blue' ? 'red' : 'blue';
}
}
};
});
Have a look at angular docs for more details

AngularJS : directives which take a template through a configuration object, and show that template multiple times

I'm looking to create a custom directive that will take a template as a property of a configuration object, and show that template a given number of times surrounded by a header and footer. What's the best approach to create such a directive?
The directive would receive the configuration object as a scope option:
var app = angular.module('app');
app.directive('myDirective', function() {
return {
restrict: 'E',
scope: {
config: '=?'
}
...
}
}
This object (called config) is passed optionally to the directive using two way binding, as show in the code above. The configuration object can include a template and a number indicating the number of times the directive should show the template. Consider, for example, the following config object:
var config = {
times: 3,
template: '<div>my template</div>'
};
It would, when passed to the directive, cause the directive to show the template five times (using an ng-repeat.) The directive also shows a header and a footer above and below the template(s):
<div>the header</div>
<div>my template</div>
<div>my template</div>
<div>my template</div>
<div>the footer</div>
What's the best way to implement this directive? Note: When you reply, please provide a working example in a code playground such as Plunker, as I've run into problems with each possible implementation I've explored.
Update, the solutions I've explored include:
The use of the directive's link function to append the head, template with ng-repeat, and footer. This suffers from the problem of the template not being repeated, for some unknown reason, and the whole solutions seems like a hack.
The insertion of the template from the configuration object into middle of the template of the directive itself. This proves difficult because jqLite seems to have removed all notion of a CSS selector from its jQuery-based API, leading me to wonder if this solution is "the Angular way."
The use of the compile function to build out the template. This seems right to me, but I don't know if it will work.
You could indeed use ng-repeat but within your directive template rather than manually in the link (as that wouldn't be compiled, hence not repeated).
One question you didn't answer is, should this repeated template be compiled and linked by Angular, or is it going to be static HTML only?
.directive('myDirective', function () {
return {
restrict: 'E',
scope: {
config: '=?'
},
templateUrl: 'myTemplate',
link: function(scope) {
scope.array = new Array(config.times);
}
}
}
With myTemplate being:
<header>...</header>
<div ng-repeat="item in array" ng-bind-html="config.template"></div>
<footer>...</footer>
I'd think to use ng-transclude in this case, because the header & footer wrapper will be provided by the directive the inner content should change on basis of condition.
Markup
<my-directive>
<div ng-repeat="item in ['1','2','3']" ng-bind-html="config.template| trustedhtml"><div>
</my-directive>
Directive
var app = angular.module('app');
app.directive('myDirective', function($sce) {
return {
restrict: 'E',
transclude: true,
template: '<div>the header</div>'+
'<ng-transclude></ng-transclude>'+
'<div>the footer</div>',
scope: {
config: '=?'
}
.....
}
}
Filter
app.filter('trustedhtml', function($sce){
return function(val){
return $sce.trustedHtml(val);
}
})

angularjs model view update through angular directive

I am trying to update my view using model in angular directive here is the directive I have created
app.directive('aboutOptions', [function() {
return {
restrict: 'C',
scope: {
testing: '='
},
transclude: true,
link: function(scope, elem, attr) {
scope.$watch(attr.ngModel, function() {
console.log(scope.$eval(attr.ngModel));
scope.testing = scope.$eval(attr.ngModel);
});
}
}
}]);
here is html model and file name is ab.html
<input type="text" class="about-options" ng-model="testing" />
Here is the view to be updated and file name is show.html
<h2 class="about-options">{{testing}}</h2>
ab.html file will be loaded as a template inside jquery ui dialog and my show.html file is in main page
If I remove
scope: {
testing: '='
},
Console is showing what I am typing
Update - 1
Tried with the following changes
testing: '=test'
And in html
<input type="text" class="about-options" ng-model="testing" />
<h2 class="about-options">{{test}}</h2>
What your doing at the end there with the scope is isolating the scope, so if an attribute called testing isn't found on the element where that directive is used you should be seeing an error in the console. If you desire an isolate scope (a good idea a lot of the time) then you'll need to provide the testing="someScopeVar" as an attribute of the element the directive is applied to.
Take a look at this repo to see how I'm doing it.
https://github.com/jedininjaster/angular-mask-money/blob/master/demo/js/angular.maskMoney.js
also take a look at the angular-ui mask directive. That is how I built my directive.
https://github.com/angular-ui/ui-utils/blob/master/modules/mask/mask.js
I apologize I don't have time right now to write a full explanation. Will try and update tomorrow

Angular : issue in my directive to get the original html content

I try too create a directive with angular. My goal is too get the original content from my html file in the compile or link function of my directive. Then update this content and for finish change the original content by the updated content in my template of my directive.
For exemple this is my index.html:
<my-directive> Hey this is my original content that I try to get! </my-directive>
This is my directive :
.directive('myDirective', function() {
return {
restrict: 'AE',
transclude: false,
template: '{{UpdatedContent}}',
compile: function(tElement, tAttr) {
console.log(tElement[0]);
},
...
The probleme is that in my compile function or link I can't get my original content each time I tried to look the tElement object I get the "{{UpdatedContent}}".
UPDATE : ANSWER
In fact the solution is to use the function transcludeFn of the compile function.
Here an exemple who works :
compile: function(elem, attrs, transcludeFn) {
var markdownContent = {};
transcludeFn(elem, function(clone) {
/* clone is element containing html that will be transcludded*/
console.log (clone.text());
});
My "clone.text()" is my original html.
I hope this will help some of you!!
You should set transclude : true, you should not do this: template: '{{UpdatedContent}}'.
If you want to get html of element on which your directive were placed in the link function just call:
tElement.html()
Btw. you always get {{UpdatedContent}} because you literally set it to be your template.
UPDATE Working PLNKR.

Custom directive in ng-repeat with isolated scope : loop items are suddenly null

I'm trying to use a custom directive in an ng-repeat loop. Without my custom directive the loop works fine: all items are displayed. But if I use my directive on the ng-repeat then all the items in the loop seem to be undefined or null, at least not printed.
Here is a simplified example:
http://jsfiddle.net/vtH64/13/
angular.module('myTest', []).directive('makecool', function(){
return {
scope: {
'flippity': '&'
},
link: function(scope, element){
element.append(", Yo!");
// do something with flippity
}
};
});
angular.module('myApp',['myTest']).controller('ListStuff', function($scope){
$scope.list = ["hi","there","this","be","a","list"];
});
It seems to have something to do with the isolated scope, because without the
scope: {
'flippity': '&'
},
which isolates the scope it works fine (http://jsfiddle.net/vtH64/15/), eventhough I will not be able to access 'flippity', which I need in the real world app.
What I am doing wrong here?
link method gets element's attributes as the third argument:
link: function(scope, element , attributes){
So you can get the flippity in a very easy way: attrs["flippity"]
Working fiddle: http://jsfiddle.net/vtH64/17/
Try with $parent if you are including the isolated scope...
<li ng-repeat="item in list" flippity="flop" makeCool>{{$parent.item}}</li>

Resources