I would like to know how attach css and templates url in a angularjs directive.
For example, with templates i have this
/*** myDirectives ***/
angular.module('myDirectives', [])
.directive('webcams', function($sce, $http, $templateCache, $compile) {
return {
restrict: 'A',
template: '<div class="included" ng-include src="getTemplateUrl();"></div>',
scope: {
stream_webcam: '=webcam',
stream_type: '#type'
},
controller: function($scope, $sce) {
$scope.getTemplateUrl = function() {
var url;
if ($scope.stream_webcam.webcam_domain == 'twitcam') {
url = 'templates/' + $scope.stream_webcam.webcam_domain + '.php';
} else if ... {
url = 'templates/second.html';
} else ...
return url;
}
...
How to put templates in my angularjs folder directive ?
Pass HTML template file to directive
you can pass by templateUrl . you can give CSS file link in your html file itself as usual.
app.directive('contactTable', ['$window',,
function($window) {
return {
scope: {
contact: "=",
},
restrict: 'A',
controller: 'contactTableController',
templateUrl: **your folder**+ '/contact-table-template.html',
link : function ($scope, element, attrs){
//your logic and dom access goes here
});
}
};
}
]);
Related
I'm trying to write a directive such that an element with attribute if-login-service="facebook" will be created, but an element with any other value for this attribute will not.
The progress I've made with this directive so far is shown below
app.directive('ifLoginService', function($compile) {
return {
restrict: 'EA',
compile: function compile(element, attrs) {
return function($scope, $element, $attr) {
var serviceName = attrs.ifLoginService;
if (serviceName === 'facebook') {
// use compile to include and compile your content here
$compile($element.contents())($scope);
}
}
}
};
});
A Plunker demo is available here. If it were working, the "Facebook" button would be displayed and the "Not Facebook" button would not. Currently both buttons are displayed, but I'm not sure where I'm going wrong.
You should use compile service to write your directive.
$compile('your html content here')($scope);
To clear root element such as button use this:
$element[0].html('');
Or remove it from DOM:
$element[0].parentNode.removeChild($element[0]);
Here is your directive repaired:
var app = angular.module('plunker', ['ngSanitize']);
app.controller('MainCtrl', function($scope) {
$scope.model = {
toggle: 'true'
};
});
app.directive('ifLoginService', function($compile,$animate) {
return {
restrict: 'EA',
replace: true,
compile: function compile(element, attrs) {
return function($scope, $element, $attr) {
var serviceName = attrs.ifLoginService;
console.debug('Testing service name', serviceName);
if (serviceName === 'true') {
// use compile to include and compile your content here
$element.html($compile($element.contents())($scope));
}
else
{
$element[0].parentNode.removeChild($element[0]);
}
}
}
};
});
Link to plunkr here
I have a controller and element directive:
ngModule
.controller('summaryCtrl', [ '$scope', '$http', function($scope, $http){
$scope.loaded = false;
$http
.get('some/item/'+itemId) //how do I get this itemId
.success(function(data){
$scope.data = data;
$scope.loaded = true;
})
.error(function(data){
//TODO
});
}])
.directive('cpSummary', function(){
return {restrict: 'E', templateUrl: 'some/path.html'};
});
and I want to use the directive something like this:
<cp-summary item-id="{id}" ng-controller="summaryCtrl"></cp-summary>
the item-id attribute get's set by the parent controller that is rendering the cp-summary elements in a ng-repeat. So I'd just like to know if it's possible to get the item-id attribute value inside the summaryCtrl.
You should use a controller for your directive. and then you can pass the item-id to the directive controller and do the stuff.
app.directive('cpSummary', function(){
return {
restrict: 'E',
templateUrl: 'some/path.html',
scope: {
item_id: '=itemId'
},
controller: ['$scope','$http',function($scope,$http) {
$http
.get('some/item/'+$scope.item_id)
.success(function(data){
$scope.data = data;
$scope.loaded = true;
})
.error(function(data){
//TODO
});
}]
};
});
As you wanted to pass id to you directive then you should include that variable inside directive isolated scope. It should be {{id}} instead of {id} & then use # inside your directive. # is for one way binding. Also assign the controller from directive.
Markup
<cp-summary item-id="{{id}}"></cp-summary>
Directive
.directive('cpSummary', function(){
return {
restrict: 'E',
templateUrl: 'some/path.html',
scope: {
item_id: '#itemId'
},
controller: 'summaryCtrl'
};
});
var app = angular.module("App", []);
app.directive("myDirective", function() {
var itemFunction = function(scope, element, attributes) {
scope.item-id= attributes["myDirective"];
};
return {
restrict: "A",
template: "<p></p>",
link: itemFunction
};
});
I have a simple angular directive I would like to pass value to.
<div my-component binding-foo="foo">
<strong>get:</strong> {{isolatedBindingFoo}} // get it to output foo?
</div>
HTML
<div my-component binding='foo'> ... </div>
JS
yourApp.controller('yourController', ['$scope', function($scope) {
$scope.isolatedBindingFoo = '';
}])
.directive('myComponent', function() {
return {
controller: 'yourController',
scope: {
'binding': '=binding'
},
link: function($scope, $element, attrs) {
$scope.isolatedBindingFoo = attrs['binding'];
}
}
});
http://fdietz.github.io/recipes-with-angular-js/directives/passing-configuration-params-using-html-attributes.html
Cheers
AngularJS mangles HTML attributes to JS properties. eg, binding-foo in HTML will be mangled to bindingFoo in JS, and vice-versa
var myModule = angular.module('myModule', [])
.controller('yourController', ['$scope', function($scope) {
$scope.isolatedBindingFoo = '';
}])
.directive('myComponent', function() {
return {
restrict:'E,A',
controller: 'yourController',
scope: true,
link: function($scope, $element, attrs) {
$scope.isolatedBindingFoo = attrs['bindingFoo'];
}
}
});
http://jsfiddle.net/b2xo0o5u/3/
But in the example case this should be enough:
angular.module('myModule', [])
.directive('myComponent', function() {
return {
restrict:'EA',
scope: {
'isolatedBindingFoo': '#bindingFoo'
}
}
});
http://jsfiddle.net/b2xo0o5u/4/
I have a directive in my module. And I want to change the templateUrl based on a attribute.
HTML
<div test stage="dynamicstage"></div>
Module
angular.module('trial', [])
.controller('trialCtrl', function ($scope) {
$scope.dynamicstage = 'Welcome';
})
.directive('test', function () {
return {
restrict: 'A',
scope: {
'stage': '='
},
link: function (scope, element, attrs) {
scope.$watch('stage', function(condition){
if(stage === 'welcome'){
templateUrl: "hello.html";
}else{
different template url...
};
});
}
}
});
This does not work. The templateurl is not loaded into the div. I want to change the templateUrl dynamically is this possible.
I appreciate any help.
This is not very transparent in Angular. templateUrl can be a function to dynamically construct template URL, however in your case you need a scope, which is not yet available at the moment URL is constructed.
You can do something like this with the help of ngInclude:
app.directive('test', function() {
return {
restrict: 'A',
scope: {
'stage': '='
},
template: '<div ng-include="templateUrl"></div>',
link: function(scope, element, attrs) {
scope.$watch('stage', function(condition) {
if (scope.stage === 'Welcome') {
scope.templateUrl = "hello.html";
} else {
scope.templateUrl = "other.html";
};
});
}
}
});
Demo: http://plnkr.co/edit/l1IysXubJvMPTIphqPvn?p=preview
Solution1 :
scope.$watch('stage', function(condition){
var templateUrl;
if(stage === 'welcome'){
templateUrl = "hello.html";
} else{
templateUrl = "someothertemplate.html";
};
//load the template;
$http.get(templateUrl)
.then(function (response) {
// template is loaded.
// add it and compile it.
angular.element(element).html(response.data);
$compile(element.contents())(scope);
});
});
Solution2:
Use ng-include
<div test stage="dynamicstage">
<div ng-include="templateUrl"></div>
</div>
Inside directive:
scope.$watch('stage', function(condition){
var templateUrl;
if(stage === 'welcome'){
templateUrl = "hello.html";
} else{
templateUrl = "someothertemplate.html";
};
scope.$parent.templateUrl = templateUrl; // make sure that templateUrl is updated in proper scope
})
I want to create a directive that has dynamic view with dynamic controller. the controller and the template view is coming from the server.
The Directive
var DirectivesModule = angular.module('BPM.Directives', []);
(function () {
'use strict';
angular
.module('BPM.Directives')
.directive('bpmCompletedTask', bpmCompletedTask);
bpmCompletedTask.$inject = ['$window'];
function bpmCompletedTask ($window) {
// Usage:
// <bpmCompletedTask></bpmCompletedTask>
// Creates:
//
var directive = {
link: link,
restrict: 'E',
scope: {
type: '=',
taskdata: '=',
controllername:'#'
},
template: '<div ng-include="getContentUrl()"></div>',
controller: '#',
name: 'controllername'
};
return directive;
function link(scope, element, attrs) {
scope.getContentUrl = function () {
return '/app/views/TasksViews/' + scope.type + '.html';
}
scope.getControllerName = function ()
{
console.warn("Controller Name is " + scope.type);
return scope.type;
}
}
}
})();
Here how I'm trying to use the directive
<div ng-controller="WorkflowHistoryController as vm">
<h2>Workflow History</h2>
<h3>{{Id}}</h3>
<div ng-repeat="workflowStep in CompletedWorkflowSteps">
<bpm-completed-task controllername="workflowStep.WorkflowTaskType.DataMessageViewViewName" taskdata="workflowStep.WorkflowTaskOutcome.TaskOutcome" type="workflowStep.WorkflowTaskType.DataMessageViewViewName">
</bpm-completed-task>
</div>
</div>
The problem now is when the directive gets the controller name it get it as literal string not as a parameter.
Is it doable ?
if it's not doable, What is the best solution to create dynamic views with its controllers and display them dynamically inside ng-repeat?
Thanks,
Update 20 Jan I just updated my code in case if some one interested in it. All the Credit goes to #Meligy.
The First Directive:
(function () {
'use strict';
angular
.module('BPM.Directives')
.directive('bpmCompletedTask', bpmCompletedTask);
bpmCompletedTask.$inject = ['$compile', '$parse'];
function bpmCompletedTask ($compile, $parse) {
var directive = {
link: function (scope, elem, attrs) {
console.warn('in the first directive - before if');
if (!elem.attr('bpm-completed-task-inner'))
{
console.warn('in the first directive');
var name = $parse(elem.attr('controllername'))(scope);
console.warn('Controller Name : ' + name);
elem = elem.removeAttr('bpm-completed-task');
elem.attr('controllernameinner', name);
elem.attr('bpm-completed-task-inner', '');
$compile(elem)(scope);
}
},
restrict: 'A',
};
return directive;
}
})();
The Second Directive
angular
.module('BPM.Directives')
.directive('bpmCompletedTaskInner',['$compile', '$parse',
function ($window, $compile, $parse) {
console.warn('in the second directive');
return {
link: function (scope, elem, attrs) {
console.warn('in the second directive');
scope.getContentUrl = function () {
return '/app/views/TasksViews/' + scope.type + '.html';
}
},
restrict: 'A',
scope: {
type: '=',
taskdata: '=',
controllernameinner: '#'
},
template: '<div ng-include="getContentUrl()"></div>',
controller: '#',
name: 'controllernameinner'
};
}]);
The Html
<div ng-repeat="workflowStep in CompletedWorkflowSteps">
<div bpm-completed-task controllername="workflowStep.WorkflowTaskType.DataMessageViewViewName" taskdata="workflowStep.WorkflowTaskOutcome.TaskOutcome"
type="workflowStep.WorkflowTaskType.DataMessageViewViewName">
</div>
</div>
Update:
I got it working, but it's really ugly. Check:
http://jsfiddle.net/p6Hb4/13/
Your example has a lot of moving pieces, so this one is simple, but does what you want.
Basically you need a wrapper directive that takes the JS object and converts into a string property, then you can use هى your directive for everything else (template, scope, etc).
.
Update 2:
Code Inline:
var app = angular.module('myApp', []).
directive('communicatorInner', ["$parse", "$compile",
function($parse, $compile) {
return {
restrict: 'A',
template: "<input type='text' ng-model='message'/><input type='button' value='Send Message' ng-click='sendMsg()'><br/>",
scope: {
message: '='
},
controller: '#'
};
}
]).
directive('communicator', ['$compile', '$parse',
function($compile, $parse) {
return {
restrict: 'E',
link: function(scope, elem) {
if (!elem.attr('communicator-inner')) {
var name = $parse(elem.attr('controller-name'))(scope);
elem = elem.removeAttr('controller-name')
elem.attr('communicator-inner', name);
$compile(elem)(scope);
}
}
};
}
]).
controller("PhoneCtrl", function($scope) {
$scope.sendMsg = function() {
alert($scope.message + " : sending message via Phone Ctrl");
}
}).
controller("LandlineCtrl", function($scope) {
$scope.sendMsg = function() {
alert($scope.message + " : sending message via Land Line Ctrl ");
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
<div ng-app="myApp">
<div ng-init="test = {p: 'PhoneCtrl', l: 'LandlineCtrl' }">
<communicator controller-name="test.p" message="'test1'"></communicator>
<communicator controller-name="test.l"></communicator>
</div>
</div>
.
Original (irrelevant now but can help other related issues)
Yes, it should work.
A test with Angular 1.3:
http://jsfiddle.net/p6Hb4/9/
Things to check:
Is the controller defined and added to the module? It will not work
If the controller is just a global function it won't work. It has to be added via the <myModule>.controller("<controllerName>", <functiion>) API
Does ng-controller work? Just adding it to the template
Similarly, does using ng-controller directly outside of the directive work?