AngularJS Directive as a comment - angularjs

I'm just playing with angular directives, but somehow the comment way to add directives is not showing up. Here is the markup.
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="angular.js"></script>
</head>
<body ng-app="directive-app">
<first-directive></first-directive>
<div first-directive></div>
<div class=first-directive></div>
<!-- directive: first-directive -->
<script src="main.js"></script>
</body>
</html>
Directive definition
var app=angular.module('directive-app',[]);
app.directive("firstDirective", function() {
return {
restrict : "EACM",
templateUrl : 'template.html'
};
});
In template.html there is one h1 element. But comment way to add directives is not showing up in UI and in which case comment approach is even required.

Set replace option to true as follows
app.directive("firstDirective", function() {
return {
restrict: "EACM",
replace: true,
templateUrl: 'template.html'
};
});
Here's demo.

Related

angularjs - access transclude html scope from hosting directive

I have a simple directive with transcluded html.
I want to be able to inject directive scope params to the transclude.
I wrote a simple example in plunker :
https://plnkr.co/edit/jqyiQdgQxbeTrzyidZYF?p=preview
I know in angular 4 it can be done, but I can't find a good way to do it in angularjs.
// Code goes here
var app = angular.module("app", []);
app.controller("mainCtrl", function($scope) {
$scope.users = ["tal", "oren", "orel", "shluki"];
$scope.deleteUser = (user) => {alert("trying to delete", user);}
});
app.directive('myList', function myList() {
return {
restrict: 'E',
transclude: true,
template: "<div><table><tr ng-repeat='item in collection'><td> This is inside myList - user name: {{item}} <ng-transclude></ng-transclude></td></tr></table></div>",
scope: {
collection: "="
},
replace: true
};
});
<!DOCTYPE html>
<html>
<head>
<script data-require="angularjs#1.6.2" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="app" ng-controller="mainCtrl">
<h1>Hello Plunker!</h1>
<my-list collection="users">
<h2>This is transclude</h2>
<button ng-click="deleteUser(user)">Delete user: {{user ? user : "User name should be here"}}</button>
</my-list>
</body>
</html>
Will really appreicate some help.
plunker: https://plnkr.co/edit/jqyiQdgQxbeTrzyidZYF?p=preview
Here's a working plunker with your example.
http://plnkr.co/edit/BjSowyQdLXd0xoCZFqZ6?p=preview
The idea is to pass it as contents and not html as string. $compile is here because the link is done after ng-repeats already has transcluded its own template.
var template = '<h1>I am foo</h1>\
<div ng-repeat="item in users">\
<placeholder></placeholder>\
<hr>\
</div>';
var templateEl = angular.element(template);
transclude(scope, function(clonedContent) {
templateEl.find("placeholder").replaceWith(clonedContent);
$compile(templateEl)(scope, function(clonedTemplate) {
element.append(clonedTemplate);
});
});
If you want a proper explanation of what the problem was you should check the detailed answer here : Pass data to transcluded element
Hope this helped you out

Wrapping md-tabs in a directive gives an "Orphan ngTransclude Directive" error

I'd like to create a directive that wraps md-tabs, but I'm getting an error, "Orphan ngTransclude Directive". I've replicated the error in this snippet:
angular.module('transcludeExample', ['ngMaterial'])
.directive('worksGreat', function(){
return {
restrict: 'E',
transclude: true,
template: '<ng-transclude></ng-transclude>'
};
})
.directive('doesntWork', function(){
return {
restrict: 'E',
transclude: true,
template: '' +
'<md-tabs md-dynamic-height>' +
'<md-tab label=\'tab 1\'>' +
'<ng-transclude></ng-transclude>' +
'</md-tab>' +
'</md-tabs>'
};
})
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-simpleTranscludeExample-production</title>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/0.11.2/angular-material.min.css">
</head>
<body ng-app="transcludeExample">
<!-- Angular Material Dependencies -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-animate.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.js"></script>
<!-- Angular Material Javascript using GitCDN to load directly from `bower-material/master` -->
<script src="https://gitcdn.link/repo/angular/bower-material/master/angular-material.js"></script>
<div>
<h3>ng-transclude in a directive works great:</h3>
<works-great>Inner text</works-great>
<hr/>
<h3>md-tabs without a directive works great:</h3>
<md-tabs md-dynamic-height>
<md-tab label="tab 1">
Inner text
</md-tab>
</md-tabs>
<hr/>
<h3>combining md-tabs with a directive doesn't work:</h3>
<doesnt-work>Inner text</doesnt-work>
</div>
</body>
</html>
I found this answer that gets into manually manipulating elements outside of the template, but I'm hoping for a cleaner "more angular" way. What's going on here? Is there a way I can define what directive the ng-transclude should apply to?
This comment on github presents the solution. ng-transclude is designed to be generic so that it can work with any directive, but in this case, that's where the problem comes from. Fortunately, it's extremely simple to mimic, and we can specify what parent it should apply to with require.
I've updated my code snippet with a working solution:
var orphanDemoCtrl = function($transclude){
this.$transclude = $transclude;
}
angular.module('transcludeExample', ['ngMaterial'])
.controller('orphanDemoCtrl', orphanDemoCtrl)
.directive('orphanDemo', function(){
return {
restrict: 'E',
transclude: true,
template: '' +
'<md-tabs md-dynamic-height>' +
'<md-tab label=\'tab 1\'>' +
'<orphan-demo-transclude></orphan-demo-transclude>' +
'</md-tab>' +
'</md-tabs>',
controller: orphanDemoCtrl
};
})
.directive('orphanDemoTransclude', function(){
return {
require: "^orphanDemo",
link: function($scope, $element, $attrs, orphanDemoCtrl){
orphanDemoCtrl.$transclude(function(clone) {
$element.empty();
$element.append(clone);
});
}
}
})
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-simpleTranscludeExample-production</title>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/0.11.2/angular-material.min.css">
</head>
<body ng-app="transcludeExample">
<!-- Angular Material Dependencies -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-animate.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.js"></script>
<!-- Angular Material Javascript using GitCDN to load directly from `bower-material/master` -->
<script src="https://gitcdn.link/repo/angular/bower-material/master/angular-material.js"></script>
<div>
<h3>combining md-tabs with a directive works now:</h3>
<orphan-demo>Inner text</orphan-demo>
</div>
</body>
</html>

How to get directive's scope value to the controller in angularjs

I have the directive that find the elements height and need to have the same value to the controller from the directive.
I tried the below mentioned code and i could not find the solution, am facing some issues.
Could anyone help me on this?
HTML
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#*" data-semver="1.2.13" src="http://code.angularjs.org/1.2.13/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<script src="controller.js"></script>
</head>
<body ng-app="myModule">
<div myDirective style="height: 300px;" ng-controller="myheight">
{{numvalue()}}
</div>
</body>
</html>
script.js for directive
angular.module('myModule', [])
.directive('myDirective', function($timeout) {
return {
restrict: 'A',
link: function(scope, element) {
scope.height = element.prop('offsetHeight');
scope.width = element.prop('offsetWidth');
}
};
})
;
contoller.js for controller
angular.module('myModule', []).controller("myheight", function($scope){
$scope.numvalue = function(){
$scope.divHeight = $scope.height;
return $scope.divHeight;
}
});
You don't need $scope.numvalue();
Your directive looks fine. Just add it to the html and change code to following.
<div ng-app="myModule">
<div style="height: 300px;" my-directive ng-controller="myHeight">
Getting height {{height}}
</div>
</div>
JSFiddle
--EDIT--
Check the updated fiddle
JSFiddle
just expose a varible of controller to the directive. after compilation process of the directive you can access the scope variable divHeight in your controller.
angular.module('myModule', [])
.directive('myDirective', function($timeout) {
return {
restrict: 'A',
scope:{
divHeight: '='
},
link: function(scope, element) {
scope.divHeight = element.prop('offsetHeight');
scope.width = element.prop('offsetWidth');
}
};
});
HTML
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#*" data-semver="1.2.13" src="http://code.angularjs.org/1.2.13/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<script src="controller.js"></script>
</head>
<body ng-app="myModule">
<div myDirective div-Height="divHeight" style="height: 300px;" ng-controller="myheight">
{{numvalue()}}
</div>
</body>
</html>

Incorporating a library in a view in Angular

I am trying to use this plugin http://prrashi.github.io/rateYo/ and for some reason when my artistpage.html page is served up the stars aren't appearing. I know the page is being served up because all other elements in the view appear. Something else that is strange is that when I put <div id="rateYo"></div> in the index.html the plugin works. So I am not really sure why its not working when the view is injected into <div ng-view></div>. Assuming my paths are correct, what could be the problem?
index.html
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js">
</script>
<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.6.0/pure-min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-route.min.js"></script>
<link rel="stylesheet" type="text/css" href="/css/styles.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<link rel="stylesheet" href="./lib/jquery.rateyo.css"/>
</head>
<body ng-app='LiveAPP'>
<div ng-view></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script src="./lib/jquery.rateyo.js"></script>
<script src="/controllers/mainCtrl.js"></script>
<script src="/controllers/signUpCtrl.js"></script>
<script src="/controllers/artistCtrl.js"></script>
<script src="/routes.js"></script>
<script src="./js/stars.js"></script>
</body>
</html>
artistpage.html
<h1>This is a title</h1>
<div id="rateYo"></div>
routes.js
angular.module('LiveAPP', ['ngRoute',
'LiveAPP.main',
'LiveAPP.signUp',
'LiveAPP.artist'])
.config(function($routeProvider, $httpProvider) {
$routeProvider
.when('/', {
templateUrl : '/home.html',
controller : 'mainCtrl'
})
.when('/signup',{
templateUrl : '/signup.html',
controller : 'signUpCtrl'
})
.when('/artist',{
templateUrl : '/artistpage.html',
controller : 'signUpCtrl'
})
});
stars.js
$(function () {
 
  $("#rateYo").rateYo({
    rating: 3.6
  });
 
});
The code in stars.js is evaluated when the document is ready, but jQuery has no knowledge of Angular replacing the view content in ng-view, so it won't attach the rating plugin to any newly added elements. Generally, you want to wrap jQuery plugins in Angular directives so that you can use them the "Angular way." For example:
app.directive("rateYo", function() {
return {
restrict: "A",
scope: {
rating: "="
},
template: "<div id='rateYo'></div>",
link: function( scope, ele, attrs ) {
$(ele).rateYo({
rating: scope.rating
});
}
};
});
Which would be used like this in your view:
<!-- assuming $scope.myRating equals the rating you want to display -->
<div rate-yo rating="myRating"></div>
Code above is untested, but it should give you the gist of it.

Angular js directive issue

Below is my code
I created a simple page and include a directive in it. And on ng-click in directive i want to call parent scope's method.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Directive Page</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"> </script>
</head>
<body>
<div ng-app="myapp" ng-controller="myController">
<ul-dir on-item-click="itemClick(obj)"></ul-dir>
</div>
</body>
</html>
<script>
var myapp = angular.module("myapp", []);
myapp.directive('ulDir', function() {
return {
restrict: 'E',
replace: 'true',
template: '<div id="container"><ul><li ng-repeat="content in contents">{{content.name}}</li></ul></div>',
controller: function ($scope) {
$scope.contents = [{'name':'Nishu', 'age':'20'},{'name':'Nidhi', 'age':'21'},{'name':'Kirti', 'age':'24'}];
},
scope: {
onItemClick: '&' // Pass a reference to the method
}
}
});
myapp.controller('myController', function($scope) {
$scope.itemClick = function(content){
console.log("Success : "+content);
};
});
</script>
So my console log print as "success : undefined"
So content object not passing from directive scope to parentscope.
Please help me.
I believe your call inside template should either be:
<a href="#" ng-click="onItemClick({'content':content})">
or
<a href="#" ng-click="onItemClick({'obj':content})">
Can you try. For more details see this SO post Can an angular directive pass arguments to functions in expressions specified in the directive's attributes?

Resources