Angular 1.4.8
How can I create directive elements programmatically inside a controller? I tried $compile but it doesn't work for me.
Controller and directive
angular.module('plunker', [])
.controller('MainCtrl', function ($scope, $compile) {
var container = angular.element(document.getElementById('container'));
$scope.user = {item: 'Axe'};
var item = angular.element(document.createElement('anItem'));
item = $compile(item)($scope);
container.append(item);
})
.directive('anItem', function(){
return {
templateUrl: 'template.html'
};
});
template.html
<p>Item: {{user.item}}</p>
index.html
...
<body ng-controller="MainCtrl">
<div id="container"></div>
</body>
...
Here is my plunker: http://plnkr.co/edit/XY6C6J70PjQTrjiwjHSz?p=preview
While the name of the directive is "anItem", the DOM elements are named "an-item". This is just the Angular naming convention. This works:
document.createElement('an-item')
Here is the updated Plunker.
var elm = angular.element('<an-item"></an-item>');
container.append(elm);
scope.$applyAsync(function () {
$compile(elm)(scope);
});
Related
I have a directive, in this directive we compile ngRepeat as you see.
my problem is :
I can't call $scope.delete() from controller, and i don't know how can compile it in my directive.
Note: run the sample
var app = angular.module("app", []);
app.controller("ctrl", function ($scope, $http) {
var root = "http://jsonplaceholder.typicode.com";
$scope.list = [];
$http.get(root + "/users").success(function (data) {
$scope.list = data;
});
///i can't call this scope
$scope.delete = function (item) {
alert("delete called");
}
});
app.directive("mydata", ["$compile", "$filter", function ($compile, $filter) {
return {
restrict: "A",
scope: {
list: "="
},
link: function (scope, element) {
var ngRepeat = element.find(".repeat").attr("ng-repeat", "item in list");
$compile(ngRepeat)(scope);
}
}
}]);
<!DOCTYPE html>
<html ng-app="app" ng-controller="ctrl">
<head>
<title></title>
</head>
<body>
<ul id="parent" mydata data-list="list">
<li class="repeat">
{{item.name}}
<button ng-click="delete()">delete</button>
</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</body>
</html>
Don't know why u are trying to do stuffs like this but a quick solution for your code is to compile the ngRepeat with the controller's scope instead of the directive the scope;
$compile(ngRepeat)(scope.$parent);
Your delete() won't fire since u are creating an isolated scope on your my-data directive. The delete() method will not get inherited.
For more conception about isolated scope and scope inheritance, check https://docs.angularjs.org/guide/directive#isolating-the-scope-of-a-directive and https://docs.angularjs.org/guide/scope
I have an angularjs sample code snippet here where i can bind the html tags using ng-bind-html directive. But how can I include some other tags like angularjs ng-click, id tag etc inside ngBindHtml directive like
Test
My sample code is here:
var app = angular.module("myApp", ['ngSanitize']);
app.controller("myCtrl", function($scope) {
$scope.myText = "<a href='#' ng-click='someFunction()'>Test</a>";
$scope.someFunction = function(){
alert("Link Clicked");
};
});
FYI, the data is loaded dynamically from server side script and i have to use ng-bind-html inside ng-repeat directive and i have to pass respective id's to click events something like ng-click="myFunction(x.id)" as in sample 2.
As suggested #Dr Jones, you need use $compile directive.
Live example on jsfiddle.
angular.module('ExampleApp', [])
.controller('ExampleController', function($scope) {
$scope.myText = "<button ng-click='someFunction(1)'>{{text}}</button>";
$scope.text = "Test";
$scope.someFunction = function(val) {
console.log(val);
};
})
.directive('bindHtmlCompile', function($compile) {
return {
restrict: "A",
scope: {
bindHtmlCompile: "="
},
link: function(scope, elem) {
scope.$watch("bindHtmlCompile", function(newVal) {
elem.html('');
var newElem = angular.element(newVal);
var compileNewElem = $compile(newElem)(scope.$parent);
elem.append(compileNewElem);
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="ExampleApp">
<div ng-controller="ExampleController">
<h3>
Write code for test button
</h3>
<textarea cols="100" ng-model="myText"></textarea>
<div bind-html-compile="myText">
</div>
</div>
</div>
I am new to angularjs ,building my first angular app now i want to display the data which i displayed right now in a table using a customized directive.
can anyone tell me how can i do this?
i just want to have a custom directive and all data should be displayed using that directive.
is customized directive should placed in a separate file?
please guide me how can i do it?
here is my controller:
'use strict';
app.controller('myAppCtrl', function ($scope, $http) {
$scope.names = []
$http.get('https://www.reddit.com/r/worldnews/new.json')
.success(function (response) {
$scope.names = response.data.children;
})
});
https://jsfiddle.net/rr6q0umb/4/
You should go through some resources online to study about angular directives .
https://docs.angularjs.org/guide/directive
http://www.tutorialspoint.com/angularjs/angularjs_custom_directives.htm
Simple directive approach for beginners
//Controller
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
});
//Directive
app.directive('simpleDemo',function(){
var newtemplate = function(){
var template = '<i class="glyphicon glyphicon-remove"><i>';
return template;
}
return {
restrict: 'E',
template: newtemplate
}
})
//html
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<button><simple-demo></simple-demo></button>
It might help you!
<html>
<head>
<title>Angular JS Custom Directives</title>
</head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
var mainApp = angular.module("mainApp", []);
mainApp.directive('student', function() {
var directive = {};
directive.restrict = 'E';
directive.template = "Student: <b>{{student.name}}</b> , Roll No: <b>{{student.rollno}}</b>";
directive.scope = {
student : "=name"
}
directive.compile = function(element, attributes) {
element.css("border", "1px solid #cccccc");
var linkFunction = function($scope, element, attributes) {
element.html("Student: <b>"+$scope.student.name +"</b> , Roll No: <b>"+$scope.student.rollno+"</b><br/>");
element.css("background-color", "#ff00ff");
}
return linkFunction;
}
return directive;
});
mainApp.controller('StudentController', function($scope) {
$scope.Mahesh = {};
$scope.Mahesh.name = "Mahesh Parashar";
$scope.Mahesh.rollno = 1;
$scope.Piyush = {};
$scope.Piyush.name = "Piyush Parashar";
$scope.Piyush.rollno = 2;
});
</script>
<body>
<h2>AngularJS Sample Application</h2>
<div ng-app="mainApp" ng-controller="StudentController">
<student name="Mahesh"></student><br/>
<student name="Piyush"></student>
</div>
</body>
</html>
Reference URLs:
https://www.airpair.com/angularjs/posts/creating-components-p3-angular2-directives
http://tutorials.jenkov.com/angularjs/custom-directives.html
http://www.sitepoint.com/practical-guide-angularjs-directives/
We mostly write our controllers in this fashion:
app.controller('MyCtrl', function($scope, $location) {
//do something with $scope & $location
});
I am writing a directive, and I am faced with a scenario where I have to render a view based on a certain controller instance. The directive will be called as follows:
<my-directive src="srcVar" controller="myctrl"></my-directive>
This directive takes care of loading the template specified by srcVar and instancing the controller using the $controller service. So there are few lines in my code that does like:
$controller(çtrlExp, {'$scope' : scope.$new() });
The above works for simple cases where the controller has only one argument. For the above controller example, you can stuff work the following manner:
var locals = { '$scope' : $scope.$new(), '$location' : $injector.get('$location') };
$controller('MyCtrl', locals);
Now how to write it for a generic case, where the user's controller can include any number of injectable constructs like services, values, constants, etc, all of which are usually defined during module creation.
Ps: if you are looking for workable code...refer my github repo: https://github.com/deostroll/ngFrame/blob/master/app/scripts/viewutils.js . This is still a work in progress sort of library.
You only need to add the $scope in your locals the rest will be done automatically by Angular's DI.
Please have a look at the demo below or this jsfiddle.
angular.module('demoApp', [])
.controller('mainController', MainController)
.directive('myDirective', MyDirective);
function MainController($scope, $location) {
this.testTemplate = 'testTemplate.html';
console.log($location, $scope); // everything available here!
}
MainController.$inject = ['$scope', '$location'];
function MyDirective($compile) {
return {
restrict: 'E',
template: 'hello',
controller: function($scope, $attrs, $controller){
console.log($attrs.controller, $scope);
$controller($attrs.controller, {'$scope': new $scope.$new()});
},
compile: function(element, attrs, $scope) {
var template = angular.element(document.getElementById(attrs.src))
.html();
console.log(template);
element.replaceWith(template);
return function(scope, element, attrs) {
//template is compiled now and in DOM, add scope variable
scope.hello='Hello from directive';
};
}
};
}
MyDirective.$inject = ['$compile'];
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp">
<script type="text/ng-template" id="testTemplate.html">
<div>
<h1>Test template</h1>
{{hello}}
</div>
</script>
<my-directive src="testTemplate.html" controller="mainController"></my-directive>
</div>
I have a custom directive and I would like to use it to include an html content to the document after clicking on it.
Plunker: http://plnkr.co/edit/u2KUKU3WgVf637PGA9A1?p=preview
JS:
angular.module("app", [])
.controller("MyController", function ($scope) {
})
.directive('addFooter', ['$compile', '$rootScope', function($compile, $rootScope){
return {
restrict: 'E',
template: '<button>add footer</button>',
controller: 'MyController',
link: function( scope, element, attrs, controller) {
element.bind( "click", function() {
scope.footer = "'footer.html'";
})}
};
}])
HTML:
<body ng-app="app">
<script type="text/ng-template" id="footer.html">
FOOTER
</script>
<div ng-controller="MyController">
<add-footer></add-footer>
<div ng-include="footer"></div>
</div>
</body>
Not sure why it is not working, as it worked fine before it was moved into the directive. Outside the directive, I was also referencing to $scope.footer with some link. I tried using $rootScope, but also no effect. Any tips please?
First. Remove unnecessary quote symbols:
element.bind( "click", function() {
scope.footer = "footer.html"; // not "'footer.html'"
});
Second. You should notify angularjs that you have asynchronously updated scope values:
element.bind("click", function() {
scope.$apply(function() {
scope.footer = "footer.html";
});
});
Or like that
element.bind("click", function() {
scope.footer = "footer.html";
scope.$apply();
});