Execute script/function on each iteration of ng-repeat - angularjs

I am using ng-repeat on an element like this:
<div ng-repeat="aSize in BC.aOutputSizesArr" style="width:{{aSize}}px; height:{{aSize}}px;">
{{aSize}}
<canvas/>
<script>alert({{aSize}})</script>
</div>
So basically on every repeat, i need to draw to the canvas based on the value of aSize, is it possible to execute a function on every iteration of ng-repeat? I tried putting that script tag in there, but it doesnt work.

Here's an example of what I mean with using a directive.
This directive:
angular.module('directives', []).directive('alerter', function () {
return {
model: {
size: '#'
},
link: function ($scope, element, attrs, controller) {
alert(attrs.size)
}
};
});
Used like:
<alerter size=10>alert 10</alerter>
<alerter size=15>alert 15</alerter>
Will execute.

You can use a custom directive or the directive ngInit
and pass a function from the controller.
This directive will execute once the tag is created by the ngRepeat.
<canva ng-init="function()"/> <!-- function from $scope -->

As #Jorg said, create a directive:
.directive('myCanvas', function(){
return {
scope: {
size: '=size'
},
template: '<canvas></canvas>',
link: function(scope, elem, attrs){
alert(scope.size);
}
};
});
Then inside your ng-repeat
<div ng-repeat="aSize in BC.aOutputSizesArr">
{{aSize}}
<my-canvas size="aSize"/>
</div>
This was quickly written and untested, but hopefully you get the idea. Just remember that the example above is just one way of binding, depending on your requirements for aSize (like can it be changed dynamically, etc).

<tr ng-repeat="app in appList" ng-init="getActivationFunction(app)"> <!-- function from $scope -->
<td><h4> {{ app.Name }} </h4></td>
<td> <img src="{{ app.ava_img }}"/> </td>
</tr>
in controller call the below function ...
$scope.getActivationFunction = function(modelRecieve) {
Service.getServiceDate(modelRecieve.name)
.then(function(response) {
var date = response.data.image;
$scope.app.ava_img = date;
},
// ...
};

Related

Angular JS: Directive content is not available in Java script function

I have a div which has ng-click. When I click on that div, it calls a function which gets script content from a Directive and I append that to another div and access the content of the script. But when I retrieve the content of the directive I am getting directive name not the content. I want to get the content.
The function I call:
$scope.someFunction = function(){
var appendHtml = $compile("<my-custom-directive></my-custom-directive>")($scope);
$("#someId").append(appendHtml)
//But when i append I am seeing as <my-custom-directive></my-custom-directive> in html not the actual content
$(""#someId"").find('script')
}
Directive:
app.directive('myCustomDirective', function ($compile) {
return {
restrict: 'E',
templateUrl: '/somecontent.html',
replace: true,
link: function ($scope, elem, attr, ctrl) {}
};
});
Somecontent.html
<script type="text/template">
<div class="arrow" style="left: 50%;"></div>
some elements here
</div>
</script>
The HTML where I call from:
<div ng-click="someFunction()">
<div id="someId">
<my-custom-directive></my-custom-directive>
//But Here I am seeing this, when calling
$(appendHtml).find('script') in my javascript function, after Javasciprt function call is done, It works fine. But i want to see actual content here when calling $(""#someId"").find('script')
<div>
</div>
it is not a good practice.
you can use ng-if and binding instead , like the follwing:
HTML
<div ng-click="someFunction()">
<div id="someId">
<div ng-if="$scope.isVisible">
<my-custom-directive></my-custom-directive>
</div>
//But Here I am seeing this, when calling
$(appendHtml).find('script') in my javascript function, after Javasciprt function call is done, It works fine. But i want to see actual content here when calling $(""#someId"").find('script')
<div>
</div>
controller:
$scope.isVisible = false;
$scope.someFunction = function(){
$scope.isVisible = true;
}
you can also pass isolate scope param to your directive and check the param in the directive template
It's possible that you're just not using jQuery or jqLite to select elements correctly.
Your someFunction might need to look more like this:
vm.someFunction = function () {
var appendHtml = $compile('<my-custom-directive></my-custom-directive')($scope);
angular.element(document).find('some-id-element').append(appendHtml);
};
I put together this plunk that I think might achieve what you're trying to do.
Does this approximate your goal?

angularJS - variable component templates

Is it possible to define a variable template for a component in angularJS 1.6?
Something like this:
<div class="test">
<{{$ctrl.GetElement()}}>
</div>
for cases in which I want to decide in runtime what the template be like.
Is there a way to do it?
Here is a simple example of a "variable template" using $compile. Let's define a "generator" directive which will be able to generate other directives:
app.directive('createDirective', function($compile) {
return {
scope: {
directiveName: '#'
},
link: function(scope, element) {
var newHtml = '<' + scope.directiveName +'></ '+ scope.directiveName +'>';
element.append($compile(newHtml)(scope));
}
};
});
This "generator" directive takes in a string (via the attribute "directive-name"), assembles new HTML, compiles it, and appends the resulting HTML to the generator directive.
I've defined a separate directive named "Hello", which I want to be called dynamically from the generator directive:
app.directive('hello', function() {
return {
restrict: 'E',
link: function(scope, element) {
element.append("Hello!");
}
}
});
Now, we can use the generator directive to compile the "Hello" directive
<div create-directive directive-name="hello"></div>
which results in this generated HTML
<hello class="ng-scope">
<!-- hello-->
Hello!
</hello>
In addition, we can pass a variable from a controller to the generator directive in a similar way:
app.controller('MainCtrl', function($scope) {
$scope.newDirective = "from-controller";
});
And in the HTML:
<div create-directive directive-name="{{newDirective}}"></div>
Be sure to take a look at the $compile documentation.
Demo

Using a function created in parent scope and also local scope varibles in an AngularJS directive with a template

So I am trying to create a directive which will replace an element with HTML which includes an ng-click which calls a function created in $scope.
An example I made can be found at http://jsfiddle.net/adinas/wbfu9ox3/5/
My HTML is
<div ng-app="myapp" ng-controller="mycontroller">
{{greeting}}
<!--This works-->
<div xyz></div>
<!--This works-->
<div ng-click="dosomething('Click me 2')">Click me 2</div>
<!--The click added in the directive here does NOT work-->
<div abc mytext="Click me 3"></div>
My JS is
var myapp = angular.module('myapp',[]);
myapp.controller('mycontroller', ['$scope', function($scope) {
$scope.greeting = 'Hola!';
$scope.dosomething = function (what) {
alert(what);
};
}]);
//Works
myapp.directive('xyz', function () {
return {
template: '<div ng-click="dosomething(\'Click me 1\')">Click me 1</div>'
};
});
//Does not work
myapp.directive('abc', function () {
return {
template: '<div ng-click="dosomething(\''+attr.mytext+'\')">Click me 3</div>'
};
});
I made 3 elements. The first two show that A. without the directive the click work. B. a directive without using the 'dosomething' function also works.
The 3rd element which tries to pass a parameter to the 'abc' directive and also call the function fails.
How can I also pass a parameter and also use the function? Thanks.
Well, if you look in the console, you will see an error that shows why this is not working:
Error: attr is not defined
You're trying to access an attr variable that doesn't exist.
The way to include attribute values in your directive template is to include them in the directive's scope:
scope: {
mytext: '#'
}
This means that there will now be a mytext variable in the scope of the directive.
This creates a problem, however, since the use of the scope: {} option creates an isolate scope for the directive, and this means that the enclosing controller's scope is not part of the directive's scope.
If feasible, the clean approach here is to also pass in the dosomething function as a parameter of the directive:
<div abc mytext="Click me 3" action='dosomething'></div>
return {
template: '<div ng-click="action(mytext)">Click me 3</div>',
scope: {
mytext: '#',
action: '='
}
};
http://jsfiddle.net/jx1hgjnr/1/
But if that's not what you want to do and you really want to access dosomething from the parent scope, one thing you can do is use $parent.dosomething:
return {
template: '<div ng-click="$parent.dosomething(mytext)">Click me 3</div>',
scope: {
mytext: '#'
}
};
http://jsfiddle.net/c815sqpn/1/
Such directive should have isolated scope, so it can be used everywhere.
That is simple directive that introduce two parameters: func and param.
app.directive('pit', function () {
return {
scope : {
func: '=',
param: '='
},
template: '<button ng-click="func(param)">Click me 3</button>'
};
});
And this is how u use it in html:
<div pit func="test1" param="test2"></div>
My plunker:
http://plnkr.co/edit/YiEWchRPwX6W7bohV3Zo?p=preview

How can I use ng-repeat to generate custom html tags or directive?

I am trying to create some custom tag using angularjs with ng-repeat but its not working, its giving tag name in double quotation marks.
Good result is: shouldn't show <div> or another tags.
I have a demo version here : http://plnkr.co/edit/aT2UjMIGGLvnCGFxXC3a?p=preview
or you can use code snippet
my code is:
angular.module('myApp', [])
.controller('MainCtrl', function($scope) {
$scope.items = [
{
"name":"directive1"
},
{
"name":"directive2"
},
{
"name":"div"
}
];
})
.directive("showitems", function(){
return {
restrict: "E",
template: '<div class="item" ng-repeat="item in items"><div class="item-title">{{item.name}}</div><div class="item-body"><{{item.name}}></{{item.name}}></div></div>'
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MainCtrl">
<showitems></showitems>
</div>
AFAIK, doing something like <{{item.name}}></{{item.name}}> will never work in angular since the markups aren't treated as new DOM elements. A much better, and more manageable approach is to write directives for all possible types you'd want to render as DOM elements.
Also, to know more about DOM manipulations from within a directive, read up about $compile: here
An alternate way of doing this would be something like this in your directive template:
<directive1 ng-if="directiveType == 'directive1'"></directive1>
<directive2 ng-if="directiveType == 'directive1'"></directive2>
<directive3 ng-if="directiveType == 'directive1'"></directive3>
And in your controller/directive, you must declare directiveType to the type of directive you want to render.
Instead of wrapping {{item.name}} into its own tag, make a customTag directive. This can take a string (the tag name) and create and compile an element with it.
.directive("customTag", function ($compile) {
return {
restrict: "A",
link: function (scope, element, attrs) {
//pass customTag in as part of the directive attribute
var customTag = attrs.customTag;
if (!customTag) return;
var customElem = angular.element("<" + customTag + "></" + customTag + ">");
//replace your custom element directive with the compiled one
element.replaceWith($compile(customElem)(scope));
}
}
}
Then in your template.html:
<div class="item" ng-repeat="item in items">
<div class="item-title">{{item.name}}</div>
<div class="item-body">
<!-- This will use customTag directive to create element item.name -->
<div data-custom-tag="{{item.name}}"></div>
</div>
</div>
A div tag (or any non-directive) wouldn't be too useful because it doesn't get any innerHTML or behavior like directive1 and directive2 would get. This of course is a simple example, you may want to put some more checks or restrictions in there, but this should get you started.
See fiddle here that builds on your example.

AngularJS - How to show custom directives based on condition

I have to show a custom directive (i.e. task-moveable) based on some condition. I have to only show the task-movable attribute for tasks which is not completed yet. Is there any way we can do this in Angularjs?
HTML Code:
<div class="gantt-body-background" ng-repeat="row in gantt.rows" task-moveable>
....
</div>
Thanks in advance.
You could make a tweak such that your taskMoveable directive can observe a value assigned to it. From there do an $eval on the value of the taskMoveable attribute to get your boolean.
As an example:
app.directive('taskMoveable', function () {
return {
controller: function ($scope, $element, $attrs) {
$scope.taskMoveable = {};
$attrs.$observe('taskMoveable', function (value) {
if (value) {
$scope.taskMoveable.amIMoveable = $scope.$eval(value);
}
});
},
template: '<span ng-bind="taskMoveable.amIMoveable"></span>'
};
});
See my plunk here for a more detailed example:
http://plnkr.co/edit/0nK4K9j3SmNnz8PgRYfR
You could use ng-if for that whole element. Something like this.
<div class="gantt-body-background" ng-repeat="row in gantt.rows" ng-if="thing.stuff" task-moveable>
....
</div>
Then that div would only be in the DOM if thing.stuff was truthy.

Resources