I am trying to compile HTML String directive which is place inside foreach loop. I even tried putting scope but still not working. My sample code looks like this:
hotelierApp.directive('maps', ['$translate', '$filter', '$compile',
function ($translate, $filter, $compile) {
return {
restrict: "A",
replace: true,
scope: true,
link: function (scope, element, attrs) {
_.each(scope.properties, function (property) {
var strHtml = $compile('<div><div class=\'hotelMarker\'>' +
'<div class=\'hotelIcon\'>' +
'<img alt=\'\' class=\'menuShadow\' src=\'{{PropertyThumbnail}}\' height=\'45\' width=\'45\'/>' +
'</div>' +
'<div class=\'hotelText\'>' +
'<span class=\'hotelHeader\'>{{PropertyName}} ' +
'</span>' +
'</div>' +
'</div></div>')(property);
return function () {
if (infoWindow) {
infoWindow.close();
}
infoWindow.setContent(strHtml[0].innerHTML);
infoWindow.open(map, markerOtherHotel, strHtml[0].innerHTML);
}
})(markerOtherHotel, property.PropertyID));
});
},
template: ''
}}]);
Please help
property is not a scope object and cannot be used with $compile in this way. Instead, you could do something like this:
var strHtml = $compile('<div><div class=\'hotelMarker\'>' +
'<div class=\'hotelIcon\'>' +
'<img alt=\'\' class=\'menuShadow\' src=\'' + property.PropertyThumbnail + '\'' +
' height=\'45\' width=\'45\'/>' +
'</div>' +
'<div class=\'hotelText\'>' +
'<span class=\'hotelHeader\'>' + property.PropertyName + ' ' +
'</span>' +
'</div>' +
'</div></div>')(scope);
See this Plunker for a working example.
Related
I have a directive that looks something like the following:
.directive('textInput', function() {
return {
restrict: 'E',
replace: true,
transclude: false,
compile: function(element, attrs) {
var html =
'<div class="form-group">' +
'<label>{{ \'' + attrs.label + '\' | translate }}</label>' +
'<input type="text" class="form-control input-sm" placeholder="' + attrs.placeholder +
'" ng-model="' + attrs.ngModel + '"' + attrs.directives + '>' +
'</div>';
var newElem = $(html);
element.replaceWith(newElem);
return function (scope, element, attrs, controller) { };
}
};
})
Note that the directives attribute was a string that added additional attribute information (e.g. tooltip info)
I have converted it to a 1.5 component but I'm not able to do the same with the directives definition.
.component('textInput', {
bindings: {
label: '#',
placeholder: '#',
directives: '<',
ngModel: '='
},
require: {
ngModelCtrl: 'ngModel'
},
template:
'<div class="form-group">' +
'<label ng-if="$ctrl.label">{{$ctrl.label | translate }}</label>' +
'<input' +
' type="text"' +
' class="form-control input-sm"' +
' placeholder="{{$ctrl.placeholder}}"' +
' ng-model="$ctrl.ngModel"' +
' {{$ctrl.directives}}>' +
'</div>'
})
<text-input directives="tooltip='foobar'"></text-input>
How can I pass in a string to the <text-input/> element such that the underlying template gets the correct information?
It is not possible, according to the docs,:
When not to use Components:
for directives that rely on DOM manipulation, adding event listeners
etc, because the compile and link functions are unavailable when you
need advanced directive definition options like priority, terminal,
multi-element when you want a directive that is triggered by an
attribute or CSS class, rather than an element
and in the same page it says that components doesn't have compile function.
I am creating a directive that will generate the HTML elements automatically according to data that received from the server.
Here is angularjs code:
(function () {
"use strict";
angular.module("workPlan").directive("myGenericFilter", ["$compile", "$http", "config", myGenericFilterData]);
function myGenericFilterData($compile, $http, config) {
var directive = {
restrict: "E",
scope: {
filterParams: "=filterparameters",
},
//templateUrl: config.baseUrl + "app/workPlan/templates/workPlanList.tmpl.html",
template: '<div></div>',
controller: "genericFilterDataController",
controllerAs: "filter",
link: function (scope, element) {
var parameters;
var el = angular.element('<span/>');
$http.post(config.baseUrl + "api/FilterConfigurations/", scope.filterParams).then(function (result) {
parameters = result.data;
angular.forEach(parameters, function (parameter, key) {
switch (parameter.ValueType) {
case 'Int32':
el.append('<div class="form-group">' +
'<div class="">' +
'<span class="view"></span>' +
'<input type="text"' + 'id =' + parameter.ObjectName + ' class="form-control">' +
'</div>' +
'</div>');
break;
case 'DateTime':
el.append('<div class="form-group">' +
'<span class="view"></span>' +
'<my-datepicker placeholder="dd/mm/yyyy" class=""></my-datepicker>' +
'</div>');
break;
}
});
});
$compile(el)(scope);
element.append(el);
}
}
return directive;
}
})();
As you can see I get data from server and according to parameter.ValueType appropriate case selected in the switch.
After the angular.forEach operator iterated on all items in the parameters variable and all DOM elements is loaded, all input HTML elements displayed except my-datepicker custom directive.
When I use F12 to Inspect Element I see the HTML code of all the elements(include my-datepicker).
Here how it's looks:
But in the view my-datepicker not displayed, here how it looks in view:
my-datepicker is custom directive that defined in common module that injected in all moduls in my project.
Any idea why my-datepicker not displayed in the view?
You compile el before the content of el is setted.
Remember that $http request is async then put
$compile(el)(scope);
element.append(el);
Into the callback
link: function (scope, element) {
var parameters;
var el = angular.element('<span/>');
$http.post(config.baseUrl + "api/FilterConfigurations/", scope.filterParams).then(function (result) {
parameters = result.data;
angular.forEach(parameters, function (parameter, key) {
switch (parameter.ValueType) {
case 'Int32':
el.append('<div class="form-group">' +
'<div class="">' +
'<span class="view"></span>' +
'<input type="text"' + 'id =' + parameter.ObjectName + ' class="form-control">' +
'</div>' +
'</div>');
break;
case 'DateTime':
el.append('<div class="form-group">' +
'<span class="view"></span>' +
'<my-datepicker placeholder="dd/mm/yyyy" class=""></my-datepicker>' +
'</div>');
break;
}
});
$compile(el)(scope);
element.append(el);
});
}
I'm new here :)
Ok I have problem, I wrote the script like this:
var app = angular.module('myApp', []);
app.directive('formInput', function() {
return {
restrict: 'E',
require: ['^form'],
link: function(scope, element, attrs, ctr)
{
var form = ctr[0];
var newEl = '<div class="control-group">' +
'<div class="controls">' +
'<input type="text" class="input-xlarge" id="' + attrs.formId + '" name="' + attrs.formId + '" required>' +
'</div>' +
'</div>' +
'<span ng-show="' + form.$name + '.' + attrs.formId + '.$error.required" class="help-block">Can\'t be blank</span>';
element.replaceWith(newEl);
}
}
});
and this html:
<div ng-app="myApp">
<form name="test321" novalidate>
<form-input required form-id="iddd" label="test"></form-input>
</form>
</div>
Im trying to get dynamic input but validation dosen't working, any one can help me please?
live link: http://jsfiddle.net/x9yuua94/
I have the code below. predictions['Team1 expected goals'] comes up as undefined in the donutChart.js directive even though the value is defined on the second line. How do I properly pass that to the directive?
<div>
<div>{{ (fixture.team1.name.short_name || fixture.team1.name.gsm_name) }}</div>
<div>{{ predictions['Team1 expected goals'] | number : 2 }}</div>
</div>
<div>
<donut-chart team1="predictions['Team1 expected goals']"
team2="predictions['Team2 expected goals']">
</donut-chart>
</div>
The below works as expected:
<donut-chart team1="1.26" team2="0.81"></donut-chart>
Here is the code for the donutChart.js directive. Note also that the structure is, an overall controller calls a directive (called models-prices) which calls this chart directive.
angular.module('stratabet')
.directive('donutChart', function(appVersion) {
'use strict';
var directive = {
priority: 0,
restrict: 'E',
scope: {
team1: '=',
team2: '='
},
controller: function($scope) {
console.log('donutChart controller - team1: ' + $scope.team1 + ', team2: ' + $scope.team2);
},
link: function(scope, element, attrs) {
console.log('donutChart - team1: ' + scope.tea1 + ', team2: ' + scope.team2);
}
}
In the line,
console.log('donutChart - team1: ' + scope.tea1 + ', team2: ' + scope.team2);
there is a typo in scope.tea1, it should be $scope.team1 as there is no property tea1 on scope
it should be
console.log('donutChart - team1: ' + scope.team1 + ', team2: ' + scope.team2);
I am trying to make a reusable modal dialog and I would like to load directive template on click directive itself..
function modalDialog() {
var directive = {
restrict: 'A',
link: linkFunc,
template: '<div class="modalBox--blur">' +
'<div class="modalBox">' +
'<h3>' {{title}} '</h3>' +
'<h4>' {{text}} '</h4>' +
'<button ng-click="answer(true)">Cancel</button>' +
'<button ng-click="answer(false)">Ok</button>' +
'</div>' +
'</div>',
scope: {
title: '=dialogTitle',
text: '=dialogTxt'
},
transclude: true
};
return directive;
function linkFunc($scope, element, attrs) {
element.on('click', function () {
$scope.newEl = element.parent();
$scope.newEl.append(...template Here...???);
});
}
}
This is how directive is set in the view:
<button
modal-dialog
dialog-title="modalBox.title"
dialog-txt="modalBox.subText"
type="button"
ng-click="deleteSth()"
class="button">
</button>
I can't figure out how to load template on element click :
element.on('click', function () {
$scope.newEl = element.parent();
$scope.newEl.append(template????);
});
Any tips?
Thank you in advance!
You can get the template with $templateCache
Like $templateCache.get('templateId.html')
Solution was compiling the template:
scope.modal = $compile(' <div class="modalBox--blur">' +
'<div class="modalBox">' +
'<h3>{{title}}</h3>' +
'<h4>{{text}}</h4>' +
'<button ng-click="dialogAnswer(true)">Annuleren</button>' +
'<button ng-click="dialogAnswer(false)">Ok</button>' +
'</div>' +
'</div>')(scope);
element.on('click', function () {
scope.newEl = element.parent();
scope.newEl.append(scope.modal);