I would like create directive with more templates.
And selected template depends on some value (like template-type).
Then if I invoke my directive in html page, and change type template-type, need changed html template.
Like this:
<template-factory template-type={{foo}}></template-factory>
I think what I can created one html template that contains all my templates, and select from ng-if help. But I think what it is not very well.
Help me please, select best solutions for this task.
Interestingly in a directive you can pass a function as your template which can then return a string which is used for the template.
Take a look at What are the benefits of a directive template function in Angularjs? to see how this is done and the pros/cons.
From the angular docs:
angular.module('docsTemplateUrlDirective', [])
.controller('Controller', ['$scope', function($scope) {
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
}])
.directive('myCustomer', function() {
return {
templateUrl: function(elem, attr){
return 'customer-'+attr.type+'.html';
}
};
});
Related
Here's one thing I'm used to do with angular directives
angular.module('app.directives').directive('login', ['$templateCache', function ($templateCache) {
return {
restrict: 'E',
template: $templateCache.get('directives/login/login.html'),
controller: 'LoginController as vm',
scope: true
};
}]);
I've grown very attached to using Template Cache to inject HTML content in my directive's template. Now with Angular 1.5 there's this new thing all the cool kids are using called component() which I'm giving a look to see if it's really good and I'm stuck at this very beginning part: how to inject things in the component itself (not in the controller)?
In this case you can see that I'm injecting into the login directive the $templateCache dependency. How would I rewrite this directive as a component? (keeping in mind my desire to use $templateCache over templateUrl)
Well, In Angular 1.5 components, template property can be a function and this function is injectable (documentation).
So, you can just use something like:
...
template: ['$templateCache', function ($templateCache) {
return $templateCache.get('directives/login/login.html')
}]
...
Few links from google search: one and two.
Hope it will help.
MaKCblMKo 's answer is right, but remember that AngularJS will check the templateCache first before going out to to retrieve the template. Therefore, you don't have to make this call in your directive or component.
angular.module('myApp', [])
.component('myComponent',{
templateUrl: 'yourGulpPattern'
})
.run(function($templateCache) {
$templateCache.put('yourGulpPattern', 'This is the content of the template');
});
https://jsfiddle.net/osbnoebe/6/
Here is my controllers.js file
(function(ctx,angular){
'use strict';
angular.module('app.controllers')
.controller('SearchMasterController',['$scope',function($scope){
//My Code
}]);
})(window, angular);
And this is my directives.js file
(function(ctx,angular){
function ControllerFunction(){
//My Controller Code
}
var directiveConfig = {
restrict:'E',
templateUrl:'path/to/acco.html',
controller: ControllerFunction
}
angular.module('app.directives')
.directive('acco', function(){
return directiveConfig;
});
})(window, angular);
Now my question is, can I use this acco directive with some different controller. Ideally, is there any way to get it working like
<acco ng-controller="SearchMasterController"></acco> ?
I tried doing,
<acco>
<div ng-controller="SearchMasterController"></div>
</acco>
and it seems to work.
Is it possible to use
<acco ng-controller="SearchMasterController"></acco> ?
The latter alternative looks ugly to me.
nice to heard this type of access, i have tried
<acco>hi{{name1}}
<div ng-controller="SearchMasterController">{{name1}}</div>
</acco>
<acco ng-controller="SearchMasterController">{{name1}}</acco>
<script>
angular.module('myApp', [])
.controller('SearchMasterController', ['$scope', function ($scope) {
//My Code
console.log("search");
$scope.name1 = 'james';
}])
.directive('acco', function () {
return{
restrict: 'E',
templateUrl: 'acco.html',
controller: function($scope) {
//My Controller Code
console.log("cntrlr fn");
$scope.name1 = 'semaj';
}
};
});
</script>
#that time i getting output as
cntrlr fn
search
cntrlr fn
means if we are using like
<acco>hi{{name1}}
<div ng-controller="SearchMasterController">{{name1}}</div>
</acco>
then we can access both controllers but when we are using like
<acco ng-controller="SearchMasterController">{{name1}}</acco>
we can't access SearchMasterController and it's not loaded also..
Yes you can use some different controller for your directive, but there is some best practice
Use controller when you want to expose an API to other directives. Otherwise use link.
The way you tried to use controller doesn't make much sense
<!--here acco and ng-controller both are directives,
in your directive's 'ControllerFunction' and ng-controller's 'SearchMasterController'
has the same controll (scope) for 'acco' rendered html.
In that case your directive's controller overrite ng-controller functionality.
So leave 'ng-controller',
if you need any functionality in your directive
then pass those functionality using =,&,#-->
<acco ng-controller="SearchMasterController"></acco>
I´ll give my best to make my problem understandable:
I have a directive. This directive handles/alters also some data it displays. Now I was wondering how I can access these data from a parent scope e.g. the controller. I am currently getting access to the scope by selecting the element and ask for the corresponding scope:
element.scope()
It works fine but it occurs to me that this is kind of a - lets say - unconventional or odd way to get the scope of an directive.
I apologize for my english (I still practicing) and hope you guys can help me. Thank you in advance :)
OK, Based on the comments your directive is some kind of a form. There are two approaches for controlling the data inside a directive:
Parent controller of a directive should control the data. In that case, Data of each directive is unique and does not share between all directives.
The directive itself should control the data. Which it means the data will be shared in all directives, and if You change one, another will be changed too.
I go with the solution number 1 which is more preferable in my guess. Let's say your template of directive is something like this,We call it template.html:
<form name="directive_from" ng-submit="submit_form()">
<input type="text" ng-model="form.name" name="username" placeholder="username"><br>
<button type="submit">Submit</button>
</form>
Because of the time,I skipped validation but you can do that easily :)
And the directive:
angular.module('app')
.directive('formDirective',function(){
return {
restrict: 'E',
templateUrl: 'template.html',
scope: {
form: '=formData',
submit_form: '#formFunc'
},
controller: ['$scope', function($scope) {
//some extra logic or binding if you need
}
}
})
OK,Now our directive which we call it formDirective accepts two parameters:
formData which is an object and holds user inserted data.
formFunc which is a function for submitting the form.
Now parent controller:
angular.module('app')
.controller('MainCtrl', ['$scope', function($scope) {
$scope.form_object = {};
$scope.submit_it = function() {
//Do whatever you like with the $scope.form_object
}
}
And let's see the view:
<div ng-controller="MainCtrl">
<form-directive form="form_object" form-func="submit_it()"></form-directive>
</div>
That's it! It's so simple example that I believe you can customize it by your needs,But the main logic for controlling the data is something like that. for example you can pass a function for ng-change on the input field or add more input fields or...
#lilly: I think you you are looking for data exchange between the parent scope and isolated scope which is possible via '='
Here is the working fiddle
angular.module('App', [])
.controller('Main', ['$scope', function ($scope) {
$scope.exchange = {};
$scope.exchange.value = "initialized by controller";
}])
.directive('inputValue', function($timeout) {
return {
restrict: 'A',
scope: {exchangeValue: '='},
link: function(scope, element, attrs) {
$timeout(function(){
scope.exchangeValue="changed by directive";
},2000);
}
};
});
http://jsfiddle.net/tiru/dJty6/43/
I'm fairly new to angularjs. Im trying to understand why it's better to use this directive, compared to just using the controller. Both examples output the same value.
Directive Example:
angular.module('docsSimpleDirective', [])
.controller('Controller', ['$scope', function($scope) {
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
}])
.directive('myCustomer', function() {
return {
template: 'Name: {{customer.name}} Address: {{customer.address}}'
};
});
Markup:
<div ng-controller="Controller">
<div my-customer></div>
</div>
Controller Example:
angular.module('docsSimpleDirective', [])
.controller('Controller', ['$scope', function($scope) {
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
}])
Markup:
<div ng-controller="Controller">
Name: {{customer.name}} Address: {{customer.address}}
</div>
Maybe I just don't fully understand directives either.
At work, we use a simple exercise to see if we need a directive or not.
If a certain snippet is used more than once, we turn it into a directive.
A directive also gives a chance to add less clutter to your templates.
angular.module('DocsSimpleDirective', [])
.controller('DocsController', [function() {
this.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
}])
.directive('myCustomer', function() {
return {
scope: true
restrict: 'EA',
controller: 'DocsController',
controllerAs: 'docsCtrls',
templateUrl: 'assets/template/my-customer.directive.html'
};
})
;
would allow your template to be defined as:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Angular test</title>
</head>
<body ng-app="DocsSimpleDirective">
<my-customer></my-customer>
</body>
</html>
and your directive as:
<article>
<strong>{{ docsCtrls.customer.name }}</strong><br>
{{ docsCtrls.customer.address }}
</article>
Personally, I try to refrain from using $scope to bind data to. If somebody else starts to read your code, a magical customer, defined in some controller somewhere on the scope is a lot harder to identify than a variable on a certain controller.
Isolating your $scope can be useful (by defining scope: true) to use a a default value. If you need to stop isolating your directives, it should be something you thought about, not because it's the default value.
When you don't isolate a scope it inherits all values that are defined in the $parentScope this is useful when nesting directives, where all directives should know which parent they originate from. This has a very distinct danger, you could manipulate data in the parentscope that shouldn't be manipulated.
https://docs.angularjs.org/api/ng/type/$rootScope.Scope
Other thing you need to set scope:true
.directive('myCustomer', function() {
return {
scope:true,
template: 'Name: {{customer.name}} Address: {{customer.address}}'
};
});
REFER THIS DOC
There are multiple possible ways of how to bind functionality to template, some are better than others.
BAD - use ng-controller attribute directly in html template to
bind controller function to it
BETTER - use ngRoute or ui-router to specify routes/states or your application and there you can specify controller and template per route/ state
BEST - use directive definiton object where you can again specify both controller and template to bind them together and then use directive inside of templates and routes.
The third example is than flexible in such a way that you can use directive just in any other template like <div my-directive></div> but also in any router as a inline template like: template: '<div my-directive></div>'
The third approach is the best because it's going in direction of components which are the future (because of React, Angular 2.0 and Webcomponents). I wrote a blog post and created a sample github repository ilustrating these concepts.
Controller:
A Controller is used to augment the Angular Scope.
When a Controller is attached to the DOM via the ng-controller directive, Angular will instantiate a new Controller object, using the specified Controller's constructor function.
controllers use to:
Set up the initial state of the $scope object.
Add behavior to the $scope object.
Do not use controllers to:
Manipulate DOM — Controllers should contain only business logic.
Format input — Use angular form controls instead.
Filter output — Use angular filters instead.
Share code or state across controllers — Use angular services instead.
Directives:
At a high level, directives are markers on a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS's HTML compiler ($compile) to attach a specified behavior to that DOM element or even transform the DOM element and its children.
Angular comes with a set of these directives built-in, like ngBind, ngModel, and ngClass.
you can create your own directives for Angular to use.
Generally directives are used to:
inject or wrapping existing thing.
Reuse same things in different palce
can inject in DOM element as attribute, element, comment or class
so if you need to reuse the same dom or logic in different place then you should use directive instead of controller.
Also you can access parent controller object from inner directive
Like:
<div data-ng-controller="mainController">
<p>hello world</p>
<some-directive></some-directive> // inject directive as element
</div>
Inspired by angular ui, I want to create front-end library as a pieces of component, all as an angularjs directive. So that the user can simply put directive with some configurations and get the desire result of component.
So this is how the directive will look like.
<date-picker
date-format="MM.DD.YYYY HH:mm"
enable-navigation
date-picker-id="datetimepicker2"
date-picker-model="myModel1">
</date-picker>
For the usage, the idea is that it could be wrapped by user-created controller and the controller can reach the directive scope like this.
<div ng-controller="myController">
<date-picker
...
date-picker-model="myModel1">
</date-picker>
</div>
(The reason I use component-name-model is because the component directive template might have more than one model) And the code in controller would be
angular.module('myApp').controller('myController',['$scope', function($scope) {
$scope.myModel1; //this scope binds to the datepicker template scope
}]);
Since I'm pretty new to angularJs, my questions are follow.
How to make the controller reach the directive scope with this syntax ? In my case, It seems that the controller didn't notice about directive scope (see my code in plunker)
Right now I'm also stuck with passing model to the template. as you can see in directive I've define date-picker-model="myModel1" and then directive will catch attrs and pass it to template like this
if('datePickerModel' in attrs){
$scope.datePickerModel = attrs.datePickerModel;
}
and when I'm using expression on templateUrl, ng-model="{{datePickerModel}}" doesn't work
The code is quite long so I would suggest you the check out my plunker
Thank you :-)
take a look at the scope parameter by creating your directive. There you can assign your 2-way binding between the controller and the directive's scope.
http://plnkr.co/edit/ngdoc:example-example85#snapshot?p=preview
<my-customer info="igor"></my-customer>
angular.module('docsIsolateScopeDirective', [])
.controller('Controller', ['$scope', function($scope) {
$scope.naomi = { name: 'Naomi', address: '1600 Amphitheatre' };
$scope.igor = { name: 'Igor', address: '123 Somewhere' };
}])
.directive('myCustomer', function() {
return {
restrict: 'E',
scope: {
customerInfo: '=info'
},
templateUrl: 'my-customer-iso.html'
};
});
also documented here: http://docs.angularjs.org/guide/directive
be also aware of the beginning symbol '=' or '#'!