Dynamically pass in an angular.js directive template property - angularjs

How can I assign a string to the template property of an angular.js directive, by passing the string as an attribute from any element that would be consuming that directive name?
For example:
In the markup:
...
Then in the angular directive:
angular.module('TestModule', [])
.directive('myCustomDirective', function(){
return {
restrict: 'AE',
template: 'my_template'
};
});
I have tried all the strategies to bind to a directive, by the use of
'#', '=' and '&' but they only help to pass values into the template but not passing
the template itself.
Any help would be appreciated please.

As suggested by New Dev, either you can compile and add your template dynamically during link function. Or you can define a fixed directive template and use ng-include to variate inner content: Like this:
template: "<div ng-include='templateToUse'></div>",
scope: {templateToUse:'='}
Now if you pass different templateToUse from where you define the directive.
<div my-directive template-to-use='determineTemplate()'></div>

Related

Pass rendered string into Angular directive

I am trying to make an angular directive that renders dynamic content urls based on an attribute placed on the directive. Example:
Directive:
angular
.module('myModule')
.directive('myContent', directive);
function directive() {
return {
replace: true,
templateUrl: function (elem, attrs) {
return attrs.contentUrl;
}
};
}
HTML:
<div my-content content-url="url/to/my-content.html"></div>
However what I would like is for the content-url attribute to be populated by a string from the controller. So let's say the controller is using the "controllerAs" syntax with the name "home", I would like the html to read:
<div my-content content-url="{{home.myContent.url}}"></div>
However within the directive's templateUrl function, the contentUrl attribute is being sent literally as "{{home.myContent.url}}". How can I get this value to evaluate before running the templateUrl function? Or, is there a better way to have simple, dynamic content available from a directive?
The answer is provided by #crhistian-ramirez:
Just use ng-include
<div ng-include="vm.myContent.url"></div>

Linking an Angular directive attribute to its template as a class with Jade

I'm trying to pass my custom Angular directive an attribute in its markup and have that attribute be assigned as a class in one of the containers of that directive's template.
Here's how my input would look, in Jade:
.form-layout-group
short-text-input.item(label="Short Input Group", inputColumnsClass="short-text-2")
Here's the function that returns my directive:
function ShortTextInput (FormControlService) {
restrict: 'E',
replace: true,
require: ['^validationForm', '?ngModel', '^?formCollection'],
scope: {
inputColumnsClass: '#'
},
templateUrl: '/templates/input/shortTextInput/short-text-input.html',
link: FormControlService.link
})
In my template, I'm trying the following:
include ../../input/_input-mixins.jade
+WrapInputwithLabelAndErrorplaceholder
div.inner-icon
div(class="{{ inputColumnsClass }}")
+InputwithValidation.item
Unfortunately, I'm not able to get this columns class to show up and actually style the input in my preferred method. When I hardcode this class into my template, what I'm intending to do works just fine.
Any tips on how I should be approaching this?
It should be input-columns-class="short-text-2".
input-columns-class DOM attribute is normalized to inputColumnsClass camel-case form by $compile service, while inputColumnsClass DOM attribute is normalized to inputcolumnsclass.

Accessing ng-repeat scope on a custom directive

I'm having a go at a directive which will dynamically load a template based on a scope value passed into it.
I am using ng-repeat on my directive, and am using the iterated item as an attribute property:
<my-form-field ng-repeat="field in customFields" field="field">
In my directive I have the following code to set the template being used.
(function() {
'use strict';
angular
.module('app')
.directive('myFormField', myFormField);
function myFormField() {
var directive = {
restrict: 'E',
scope: {
field: '='
},
link: function(scope){
scope.getContentUrl = function() {
return 'app/modules/form_components/form_field/' + scope.field.type + '-template.html';
}
},
template: '<div ng-include="getContentUrl()"></div>'
};
return directive;
}
})();
Whilst the above works (which I found from other posts), I wonder if there is a better way.
For example I have seen examples of calling a function on the templateUrl config option instead, and then in that function access the scope attributes being passed in. When I tried this way, my field attribute was a literal 'field' string value (they are objects in my customFields array), so I think at that point the scope variables had not yet been evaluated.
With this current solution I am using, all of my templates get wrapped in an extra div since I am using ng-include, so I am just trying to make the rendered markup more succinct.
Any suggestions\advice is appreciated.
Thanks

AngularJS directive that contains ng-bind-html directive

I want this piece of code
<test data="myObject"></test>
to be rendered as
<p>raw html code that is stored inside myObject.html</p>
My directive
module.directive('test', function() {
return {
restrict: 'E',
template: '<p ng-bind-html="__what_to_do_here__?"></p>',
scope: {
// This object has a html propery which contains raw html.
data: '='
}
};
});
How can i pass the raw html variable to the ngBindHtml directive in my template?
Did you include ngSanitize? I think it is required to be able to render html from a variable.
You can find more information about ng-bind-html here: https://docs.angularjs.org/api/ng/directive/ngBindHtml (will also link you to ngSanitize)

angular directive attributes isolate scope undefined outside ng-repeat

I have directive this directive:
myApp.directive('myDirective',['$http', function($http) {
return {
restrict: 'AEC',
replace: true,
scope: { attr1: '=' , attr2: '=' },
link: function(scope, element, attrs) {
...
}
}]);
If I put directive inner ng-repeat it works, so I have acces to value of attributes (eg. scope.attr1)
<div ng-repeat="item in items"
<my-directive attr1="item.value1" attr2="item.value2"></my-directive>
</div>
but if I put directive outside ng-repeat, so I have only my-directive:
{{mymodel.value1}} {{mymodel.value2}} //{{}} print correct value
<my-directive attr1="mymodel.value1" attr2="mymodel.value2"></my-directive> //this fail
I can't access to attributes, so If I access eg. scope.attr1 I'm getting undefined value.
the "item" object is only defined in the div with the ngRepeat so when you are trying to access specific items from the list "items" outside of the div with ngRepeat you have to use items[index].value1 syntax. Try:
<my-directive attr1="items[index].value1" attr2="items[index].value2"></my-directive>
If the values are simple types, you should use '#' instead of the two-way model binding that '=' implies.
Also how are you reading your values. Do you read them through scope.attr1 or attrs['attr1'] - since the attr collection only holds the value in the attributes, whereas the scope actually lnks to the objects
There should be nothing wrong with your code. Maybe you could spot what you're doing differently:
Working Example Here

Resources