I have a directive which loads a template with a bunch on input fields. One of which is the jQuery/Bootstrap datepicker.
<my-directive-buttons></my-directive-buttons>
When a user selects/clicks on the datepicker field, the calendar is displayed. I have also attached an ng-click
to the input field:
<div class='col-sm-6'>
<div class="form-group">
<div class='input-group datepick'>
<input type='text' class="form-control" ng-click="addCalendarFooter()"/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
On click, the calender is displayed and $scope.addCalendarFooter
is called:
app.directive('myDrectiveButtons', function($compile) {
return {
restrict: 'E',
replace: true,
transclude: true,
scope: {
},
templateUrl: 'controls/input-fields.html',
link: function(scope, elem, attrs) {
},
controller: function($scope) {
$scope.addCalendarFooter = function() {
$('#datepicker').append($('<div></div>').load('myDir/calendar/customFooter.html'));
}
}
}
});
I am successful in appending the contents of customFooter.html
to the calendar, however, within customFooter.html
are further ng-clicks
, which when pressed, are not being called. E.g
customFooter.html
<div>
<button ng-click="controlClick()">Click Me</button>
</div>
Yet, if i move this button out of customFooter.html
and in to input-field.html
, to test the button logic is correct, the click is called.
I have tried $scope.$apply
and $scope.digest
after the .append
, however i get a 'digest already in progress error'
UPDATE:
Based on comments, below, have tried to remove jQuery and use an 'angular way'
$scope.addCalendarFooter = function() {
var html = "<div ng-include src=\"myDir/calendar/customFooter.html\"><\div>";
var myEl = angular.element(document.getElementsByClassName('datepicker');
myEl.html(html);
$compile(myEl)($scope)
}
The above inserts my .html template via the ng-include however is it replacing the contents of the datepicker rather than inserting at the bottom of it. Tried .append but that didn't worth either.
Quoting from your UPDATE:
The above inserts my .html template via the ng-include however is it replacing the contents of the datepicker rather than inserting at the bottom of it. Tried .append but that didn't worth either.
The aforementioned issue is due to using .html()
method which inserts HTML to a DOM node and overwrites any existing content of the selected node:
var html = "<div ng-include src=\"myDir/calendar/customFooter.html\"><\div>";
var myEl = angular.element(document.getElementsByClassName('datepicker');
myEl.html(html); // <== here
$compile(myEl)($scope)
What you are doing with the above logic is that you first select the .datePicker
element, then you replace its inner HTML with the .html()
method.
As a workaround, you could have used .append()
method instead.
NOTE: angular.element()
is Angular's wrapper for an element just as in jQuery
you had $()
. Therefore, using document.getElementByClassName()
method is redundant in your case.
Although the above workaround might solve your problem, but it is better to stick to a cleaner and concise approach which AngularJS may offer.
You don't need to load a template partial by programmatically adding/appending the template in a controller function - at least in Angular's way. This way you might end up not binding the angular directive(s) within the dynamically added HTML correctly with a scope.
Instead, just include the partial within the original directive template (with ng-include
) and use ngIf
or ngShow
to display it when the button is clicked.
Therefore, assuming that you've the footer template (customFooter.html
) in the original directive template, you can achieve the expected result as in the following:
<div class='col-sm-6'>
<div class="form-group">
<div class='input-group datepick'>
<input type='text' class="form-control" ng-click="addCalendarFooter()"/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
<div ng-include="myDir/calendar/customFooter.html" ng-if="isCalenderFooterAdded"></div>
controller: function($scope) {
$scope.addCalendarFooter = function() {
$scope.isCalendarFooterAdded = true;
// or use this if you want to toggle it
// $scope.isCalendarFooterAdded = !$scope.isCalendarFooterAdded ? true: false;
}
}