Attempting to incorporate ngModel
into an Angular directive results in the following error:
Error: [$injector:unpr] Unknown provider: ngModelProvider <- ngModel
http://errors.angularjs.org/1.2.18/$injector/unpr?p0=ngModelProvider%20%3C-%20ngModel
at http://localhost:2013/Scripts/angular.js:78:12
at http://localhost:2013/Scripts/angular.js:3741:19
at Object.getService [as get] (http://localhost:2013/Scripts/angular.js:3869:39)
at http://localhost:2013/Scripts/angular.js:3746:45
at getService (http://localhost:2013/Scripts/angular.js:3869:39)
at invoke (http://localhost:2013/Scripts/angular.js:3896:13)
at Object.instantiate (http://localhost:2013/Scripts/angular.js:3917:23)
at $get (http://localhost:2013/Scripts/angular.js:7201:28)
at http://localhost:2013/Scripts/angular.js:6592:34
at forEach (http://localhost:2013/Scripts/angular.js:327:20) angular.js:9937
(anonymous function) angular.js:9937
$get angular.js:7283
$get.Scope.$digest angular.js:12414
$get.Scope.$apply angular.js:12660
done angular.js:8272
completeRequest angular.js:8477
xhr.onreadystatechange
The directive code is as follows:
module.directive("myDatePicker", function () {
return {
restrict: "A",
template: '<p class="input-group" title="{{title}}">' +
'<input type="text" class="form-control" data-datepicker-popup="{{dateFormat}}" ng-model="selectedDate" data-is-open="isOpen" data-datepicker-options="dateOptions" ng-required="true" data-close-text="{{closeText}}" />' +
'<span class="input-group-btn">' +
'<button type="button" class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>' +
'</span>' +
'</p>',
replace: true,
require: '?ngModel',
//priority: 0,
scope: {
title: "@",
selectedDate: "=ngModel",
onChange: "&",
dateFormat: "="
},
compile: function (tElement, tAttrs, transclude) {
// Correct ngModel for isolate scope
if (tAttrs.ngModel) {
tAttrs.$set('selectedDate', tAttrs.ngModel, false);
tAttrs.$set('ngModel', 'selectedDate', false);
}
return {
post: function (scope, iElement, iAttrs, controller) {
// Render
return controller.$render = function () {
if (!controller.$viewValue) {
return;
}
angular.extend(scope, controller.$viewValue);
};
}
};
},
priority: 100,
link: function (scope, elem, attr) {
},
controller: function ($scope, global, ngModel) {
$scope.isOpen = false;
$scope.closeText = 'Close';
$scope.dateOptions = {};
$scope.open = function ($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.isOpen = true;
};
$scope.$watch(function () {
return $scope.selectedDate;
},
function (newValue, oldValue) {
ngModel.$setValidity('required', newValue == true);
$scope.onChange({ newDate: newValue, oldDate: oldValue });
}, true);
}
};
});
Here is the corresponding HTML snippet:
<input data-my-date-picker
id="EventDatePicker" data-name="EventDatePicker"
data-date-format="dateFormat"
ng-model="EventDetails.Date"
ng-required="true"
data-title="Date" />
Why is the injection not resolving? Attempts have been made like:
module.directive("myDatePicker", ['ngModel', function () {
...but this did not resolve the issue.
The removal of priority
also yielded no solution.
Could it be related to the loading order of directives?
What might be missing here?
After implementing sma's suggestion, the following change was applied:
require: ['^ngModel'/*, '^isDate'*/],
scope: {
title: "@?",
name: "@?"
},
link: function (scope, elem, attr, ngModel/*, isDate*/) {
...
This appears to have partially resolved the issue.
The inability to inject this into the controller remains a mystery. :(
There must be a solution out there, waiting to be discovered...
In a puzzling turn of events, other directives like isDate
are still not being injected (despite being defined before the current directive).
This situation is perplexing.