$compile service in angular returns an array - angularjs

I am trying to compile a static DOM against scope using the following code
(function(angular) {
var app = angular.module("directiveModule1",[]);
app.controller('testController', ['$scope', function($scope){
$scope.UserName = "afh";
}]);
app.directive("linkFuncDirective",['$compile', function($compile) {
return {
link: function(scope, element, attrs,controller) {
var markUp = "<input type = 'text' ng-model ='UserName'/>{{UserName}}</br>";
var linkFunc = $compile(markUp);
var content = linkFunc(scope);
angular.element(element).html(content);
//angular.element(element).html($compile(markUp)(scope));
}
};
}]);
})(window.angular);
and my html is below
<html>
<head>
<script data-require="angular.js#*" data-semver="1.4.0-beta.5" src="https://code.angularjs.org/1.4.0-beta.5/angular.js"></script>
<script src="directiveWithLinkFunction.js"></script>
</head>
<body ng-App="directiveModule1">
<div ng-controller="testController">
<div link-func-directive></div>
</div>
</body>
</html>
and I get the following o/p
[[object HTMLInputElement], [object HTMLSpanElement], [object HTMLBRElement]]
Trying to understand what was written wrong in code, any help is highly appreciated

The reason behind html is having [[object HTMLInputElement], [object HTMLSpanElement], [object HTMLBRElement]] on view is, You have compiled one line of html using $compile service which returns below as compiled DOM
<input type="text" ng-model="UserName">
<span class="ng-binding ng-scope"></span>
<br class="ng-scope">
So basically it has 3 elements, 1st one is input element, 2nd is span & 3rd is br break tag. So when you try to add it as HTML to page using .html method, jQLite internally takes that object and apply .toString() method to making sure it should accept the string. That's the reason why you are getting [Object...] in the output.
Basically your problem is you are assigning compiled angular DOM html content to the directive element html, which wouldn't make sense.
It should be .append function instead of .html as angular compiled DOM will get injected will have binding enabled.
element.append(content); //would append the DOM with angular compiled DOM.

Why do you want to compile that in the first place ? You can use a simple template for that.

Your code is a little bit mess. Try to clean up first.
give a restrict property to your directive
if you don't have a required field then you don't need a controller parameter
Why don't you just simple use a template for your directive

Related

Regarding angular js directives usage

i am learning angular so when reading article then some time getting stuck to understand the output. here i confusion of render html output.
code taken from http://www.w3schools.com/angular/tryit.asp?filename=try_ng_directive
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" w3-test-directive></div>
<script>
var app = angular.module("myApp", []);
app.directive("w3TestDirective", function() {
return {
template : "I was made in a directive constructor!"
};
});
</script>
</body>
</html>
when the above code runs then output as follows
<div w3-test-directive="" ng-app="myApp" class="ng-scope">I was made in a directive constructor!</div>
my question is why the directive's template text gets added within start and end div tag ?`
why this attribute is blank w3-test-directive="" in div ?
this text I was made in a directive constructor! could have added in the attribute of w3-test-directive so the html output may look like
<div w3-test-directive="I was made in a directive constructor!" ng-app="myApp" class="ng-scope"></div>
please help me to understand why the directive's template text gets added within start and end div tag ?` thanks
How you use directives depends on the 'restrict' property.
If you add restrict: 'E', then you can use it as a element, ex:
<foo></foo>
If you do restrict: 'A', now its:
<div foo></div>
More info:
http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-i-the-fundamentals
Example:
angular.module('moduleName')
.directive('foo', function () {
return {
restrict: 'EA', //E = element, A = attribute, C = class, M = comment
template: 'Foo'
}
});
The template or the content from templateURL is always inserted between the enclosing tags on which the directive is used. Hence the template text added inside the div tags. This happen because untill it gets to html, it will never be displayed.
w3-test-directive="" : this is because of the fact that this as a attribute has no value. Since it not a known attribute in html, it has no default value, so it will be parsed like this.
I have added an example where i am using the same directive as an element tag instead of using it as a attribute
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp">
<w3-test-directive></w3-test-directive>
</div>
<script>
var app = angular.module("myApp", []);
app.directive("w3TestDirective", function() {
return {
template : "I was made in a directive constructor!"
};
});
</script>
</body>
</html>
A directive renders its template within the element upon which it is declared. The w3-test-directive directive is being declared (as an attribute) on your div element:
<div ng-app="myApp" w3-test-directive></div>
It will therefore render your template within that element's opening and closing tags, and won't (by default) affect anything higher in the DOM tree.
Also, about valueless attributes - they don't need values. For example, the disabled or async attributes do not normally have values. That a particular attribute is merely present is enough, in many cases. In Angular, the presence of a directive, declared as an attribute, is often all that is needed. If you provide values, they will be interpreted as references to model data (handled by the your scope declaration within the directive definition).
why this attribute is blank w3-test-directive="" in div ?
blank space is because it show that attributes as Html5 compliance no html5 errors or warnings. same as if we write disable or readonly property.
ng-directives have menu types to declare for example :
<div ng-app="myApp" w3-test-directive></div>
above example of 'A' means Attribute it can be write as follows:
following example with 'E' Element
<div ng-app="myApp">
<w3-test-directive></w3-test-directive>
</div>
following example with 'C' Class
<div ng-app="myApp">
<span class='w3-test-directive'></span>
</div>
for more info please refer following link:
[angular directives][1]
[1]: https://docs.angularjs.org/guide/directive

How to parse multiple variables via ng-click into a angularjs function

I'm new to angularJS and can't seem to figure out how to parse multiple variables from a html button thru an angular JS function.
<html ng-app="">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
</head>
<body ng-controller='CartController'>
<script>
function CartController($scope) {
$scope.addToCart = function(index,product) {
alert(product);
};
}
</script>
<button ng-click="addToCart(2,iPhone);">Add to cart</button>
</body>
</html>
I would expect the second variable (iPhone) would get stored in variable named product but the alert shows its undefined.
What am I doing wrong?
Try using ng-click="addToCart(2,'iPhone');"
What you want is to pass the string 'iPhone', not a property on the $scope called iPhone.
Without the quotes, it will be evaluated against the $scope in CartController. There is no iPhone property on $scope so it will be undefined.
Your original try would work if in CartController you'd have:
$scope.iPhone = "Hello";
The string Hello would be passed to the addToCart function.

Angularjs | how to get an attribute value from element in which controller is defined

I'm still fighting with simple things in Angular. I have jQuery and Backbonejs background, so please do not yell on me. I try hard to understand differences
I have HTML in which from rails is given ID of project as data-project-id:
<div data-ng-controller="ProjectCtrl as ctrl" data-project-id="1" id="project_configuration">
Is there any chance to get access to this attribute? I need it to my API calls...
To access an elements attributes from a controller, inject $attrs into your controller function:
HTML
<div test="hello world" ng-controller="ctrl">
</div>
Script
app.controller('ctrl', function($attrs) {
alert($attrs.test); // alerts 'hello world'
});
In your example, if you want to get data-project-id:
$attrs.projectId
Or if you want to get id:
$attrs.id
Demo:
var app = angular.module('app',[]);
app.controller('ctrl', function($attrs) {
alert($attrs.test);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl" test="hello world">
</div>
In Angular world you should use directives to manipulate with DOM elements. Here a nice explanation how to get attribute value from custom directive (How to get evaluated attributes inside a custom directive).
But if you still want to get it's value from controller you are able to use jQuery as well $('#project_configuration').data('project-id')

Angularjs controller nesting

I'm new to angular, I've tried some testing pattern and it's ok with the $scope variable but I can't make it work for a simple controller nesting. (and avoid using the $scope variable, instead I want to use "this")
Here is my sample HTML and javascript :
<!doctype html>
<html ng-app="appTest">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
</head>
<body>
<div ng-controller="FirstController as first">
<div>
First is {{first.text}}
</div>
<div ng-controller="SecondController as second">
Second is {{second.text}}
</div>
</div>
<script>
var app = angular.module("appTest",[]);
function printFirst() {
this.text = "first"
}
function printSecond() {
this.text = "second";
}
app.controller("FirstController",[printFirst]);
app.controller("SecondController",[printSecond]);
</script>
</body>
</html>
In the output html the angular variables inside curly brackets are not replaced and I don't know what's going on. I've tried to install Angular Batarang for debugging but the scope console is empty.
Obviously it's a silly mistake but I don't see where I'm wrong
Ok, the answer has nothing to do with my code, I was just using a too old version of Angularjs (1.0.8).
I moved to the last version 1.3.4 and it works fine.
Access the variable using $scope.text please instead of this.text.

How to bind data using Angular in my case?

I am trying to create a tooltip based from from this post
Angular-UI-Bootstrap custom tooltip/popover with 2-way data-binding
I successfully created the popup but I have trouble delivering the content to my popover.html
I added this to my script.js
var app = angular.module('myApp', ['ui.bootstrap', 'ian.bootstrap']);
app.controller('myCtrl', function ($scope) {
$scope.item = {
title: 'Original Title',
content:'content 1' //newly added item
};
$scope.text = 'Click me';
});
and I want to display it in my popover.html
<div class="popover-content">
{{item.content}}
</div>
It doesn't show anything. Can someone help me about it? thanks a lot!
my plunker
http://plnkr.co/edit/5pBZ9qq79OPl2tGEeYYV?p=preview
Here is your updated working Plunkr
Basically you have to pass the attr iantooltip-content with the binding of the content item, not the raw text, and after in the directive pass in the directive isolate scope options the binding of the content like :
iantooltipContent: '='
Just change the appenToBody variable and you're done.
You should read the docs for more infos about Angular directive :)
You can add the ng-controller in your div and then specify the controller name like so :
<div class="popover-content" ng-controller='myCtrl'>
{{item.content}}
</div>
Before the use cases, the basic syntax to create a custom directive.
For all the code samples in this page I started from the angular-seed template.
Starting from the angular-seed skeleton is quite easy to extract a model to begin to implement custom directives.
<html ngApp="myApp">
...
<div my-first-directive></div>
<script src="lib/angular/angular.js"></script>
<script src="js/app.js"></script>
<script src="js/directives.js"></script>
...
</html>

Resources