Google is giving me the error: "TypeError: Cannot read property 'open' of undefined" in response to my ui-bootstrap module. I've been using other ui-bootsrap directives fine.
Am I not declaring the modal dependency correctly?
angular.module('ireg').directive('study', function (studyFactory) {
return {
restrict:'E',
scope: {
objectid:'#objectid'
},
templateUrl: '/ireg/components/study/study.html',
link: function (scope, element, attrs, $modal) {
scope.openMilestonesDialog = function () {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: '/ireg/components/add-milestones/addMilestonesDialog.html',
controller: '/ireg/components/add-milestones/addMilestonesDialogController.js',
size: lg
});
};
}//end of link
}
});
angular.module('ireg').controller('addMilestonesDialogController', function ($scope, $modalInstance, studyId) {
$scope.ok = function () {
$modalInstance.close();
};
});
You should include $modal service in your directive function instead of link function:
angular.module('ireg').directive('study', function (studyFactory, $modal) {
return {
restrict:'E',
scope: {
objectid:'#objectid'
},
templateUrl: '/ireg/components/study/study.html',
link: function (scope, element, attrs) {
scope.openMilestonesDialog = function () {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: '/ireg/components/add-milestones/addMilestonesDialog.html',
controller: '/ireg/components/add-milestones/addMilestonesDialogController.js',
size: 'lg'
});
};
}//end of link
}
});
And yes, Alberto I.N.J. is right, you should set size attribute as string.
You should inject $model into directive itself and change lg to 'lg'
angular.module('ireg').directive('study', function (studyFactory, $modal) {
return {
restrict:'E',
scope: {
objectid:'#objectid'
},
templateUrl: '/ireg/components/study/study.html',
link: function (scope, element, attrs) {
scope.openMilestonesDialog = function () {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: '/ireg/components/add-milestones/addMilestonesDialog.html',
controller: '/ireg/components/add-milestones/addMilestonesDialogController.js',
size: 'lg'
});
};
}//end of link
}
});
Related
i'm using ngimgcrop to crop images and it works fine in but I tried to display the images inside uibmodal it doesn't work.
I tried some solutions(use ng-init ..)but None worked for me.
and in the console the image is empty.
here is my controller :
var app = angular.module('app', ['ngImgCrop', 'ui.bootstrap']);
app.controller('Ctrl', ['$scope',
'$rootScope',
'$uibModal',
'$log',
function($scope,
$rootScope,
$uibModal,
$log)
{
$scope.animationsEnabled = true;
$scope.open = function (size) {
// alert('open mthod is called');
$scope.test = 5;
var modalInstance = $uibModal.open({
animation: true,
ariaLabelledBy: 'modal-title',
ariaDescribedBy: 'modal-body',
templateUrl: "imageModal.html",
controller: 'Ctrl',
controllerAs: '$ctrl',
size: size
});
modalInstance.result.then(function (selectedItem) {
$log.info('selected value:'+selectedItem);
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
$scope.size='small';
$scope.type='circle';
$scope.imageDataURI='';
$scope.resImageDataURI='';
$scope.resImgFormat='image/png';
$scope.resImgQuality=1;
$scope.selMinSize=100;
$scope.resImgSize=200;
$scope.test=225;
//$scope.aspectRatio=1.2;
$scope.onChange=function($dataURI) {
console.log('onChange fired');
};
$scope.onLoadBegin=function() {
console.log('onLoadBegin fired');
};
$scope.onLoadDone=function() {
console.log('onLoadDone fired');
};
$scope.onLoadError=function() {
console.log('onLoadError fired');
};
$scope.uploadFile = function(file) {
if (file) {
// ng-img-crop
var imageReader = new FileReader();
imageReader.onload = function(image) {
$scope.$apply(function($scope) {
$scope.imageDataURI= image.target.result;
});
};
imageReader.readAsDataURL(file);
$scope.open();
}
};
console.log(' my image', $scope.imageDataURI);
$scope.$watch('resImageDataURI',function(){
console.log('Res image', $scope.resImageDataURI);
});
}]);
imagemodal.html :
<div ng-if="enableCrop=true" class="cropArea" ng-class="{'big':size=='big', 'medium':size=='medium', 'small':size=='small'}">
<img-crop image="imageDataURI"
result-image="$parent.resImageDataURI"
change-on-fly="changeOnFly"
area-type="{{type}}"
area-min-size="selMinSize"
result-image-format="{{resImgFormat}}"
result-image-quality="resImgQuality"
result-image-size="resImgSize"
on-change="onChange($dataURI)"
on-load-begin="onLoadBegin()"
on-load-done="onLoadDone()"
on-load-error="onLoadError()"
></img-crop>
<!--aspect-ratio="aspectRatio"-->
Demo:
demo
If yout want to show cropped image from controller to modal, using resolve in this parametr put variable result-image of img-crop. just like :
var modalInstance = $uibModal.open({
animation: true,
ariaLabelledBy: 'modal-title',
ariaDescribedBy: 'modal-body',
templateUrl: "imageModal.html",
controller: 'Ctrl',
controllerAs: '$ctrl',
size: size,
resolve:{
croppedImg:$scope.imageCrop
}
});
when your imageCrop look like
<img-crop image="imageDataURI"
result-image="imageCrop"
in modal controler inject croppedImg as normal provider/service/factory just like:
function Ctrl($scope, croppedImg, ..another, ..etc)
in this way, in controller you got cropped image in your modal controler. Then only
$scope.newImg = croppedImg
and show in modal as <img src="{{newImg}}">
Hope you understand.
When opening a bootstrap ui modal, if you prefer to use a directive, rather than separately a templateUrl and controller, how can you then in the controller of the directive for the modal, access $uibModalInstance in order to close the modal or whatever you need to do? Also, how can we pass items without having to add it as an attribute on the template?
angular.module('myModule', ['ui.bootstrap'])
.directive('myDirective', ['$timeout', function ($timeout) {
var controllerFn = ['$scope', '$uibModal', function ($scope, $uibModal) {
$scope.names = ['Mario','Wario','Luigi'];
$scope.openModal = function () {
var modalInstance = $uibModal.open({
animation: true,
template: '<my-modal>',
size: 'lg',
resolve: {
items: function () {
return $scope.names;
}
}
});
};
}];
return {
restrict: 'E',
templateUrl: '/Folder/my-directive.html',
controller: controllerFn,
scope: {
}
};
}])
.directive('myModal', ['$timeout', function ($timeout) {
var controllerFn = ['$scope', function ($scope) {
}];
return {
restrict: 'E',
templateUrl: '/Folder/my-modal.html',
controller: controllerFn,
scope: {
}
};
}]);
I use something like that to send parameter to modal, add an element to array and give it back to directive.
// Directive who open modal
.directive('myDirective', ['$timeout', function ($timeout) {
var controllerFn = ['$scope', '$uibModal', function ($scope, $uibModal) {
// Base array
$scope.names = ['Mario','Wario','Luigi'];
$scope.openModal = function () {
// Modal instance
var modalInstance = $uibModal.open({
animation: true,
template: '<my-modal>',
size: 'lg',
controller: 'myDirectiveModalCtrl',
controllerAs: '$modalController',
resolve: {
// Provide namesInModal as service to modal controller
namesInModal: function () {
return $scope.names;
}
}
});
// When modal close, fetch parameter given
modalInstance.result.then(function (namesFromModal) {
$scope.names = namesFromModal;
}, function () {
// $log.info('Modal dismissed at: ' + new Date());
});
};
}];
return {
restrict: 'E',
templateUrl: '/Folder/my-directive.html',
controller: controllerFn,
scope: {
}
};
}])
// Modal controller
.controller('myDirectiveModalCtrl', ['$uibModalInstance','namesInModal',
function ($uibModalInstance, namesInModal) {
// Use same name set in myDirective.controllerAs
var $modalController = this;
// Get provided parameter as service
$modalController.names = namesInModal;
// Add new element
$modalController.names.push('peach');
// Return modal variable when close
$modalController.ok = function () {
$uibModalInstance.close($modalController.names);
};
$modalController.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
}
]);
In the directive's link function, $uibModalInstance is available on the scope object.
I use https://github.com/simpulton/angularjs-wizard for my project, it works,
(I modified it a little, replaced var app to $scope)
but I need to pass a variable to open function:
$scope.open = function (image)
{
$scope.image = image;
var modalInstance = $uibModal.open({
templateUrl: 'wizard.html',
controllerAs: 'modal',
size: 'lg',
controller: 'ModalCtrl',
resolve: {
image: function () {
return image;
}
}
});
modalInstance.result
.then(function (data) {
$scope.closeAlert();
$scope.summary = data;
}, function (reason) {
$scope.reason = reason;
});
};
and in html:
ng-click="open(image)"
but image is undefined in my template
it works if I only just the modal window, with the example from https://angular-ui.github.io/bootstrap/#/modal,
but not with this wizard example
update:
https://jsfiddle.net/Ginstay/znz64sk3/2/
yes, ajax is completed at the moment, when I open the modal window
and if I add a breakpoint to return image; image is there
Try this one
angular.module('plunker', ['ui.bootstrap']);
var ModalDemoCtrl = function ($scope, $modal) {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl,
resolve: {
test: function () {
return 'test variable';
}
}
});
};
var ModalInstanceCtrl = function ($scope, $modalInstance, test) {
$scope.test = test;
};
I figured it, I needed to add
$scope.image = image;
to ModalCtrl
I want to call alertForm directive in loginForm directive. Where I want call 'alertForm' directive in 'loginForm' is highlighted as //i want to call here
alertForm directive
angular.module('myApp')
.directive('alertForm', function () {
return {
templateUrl: 'app/directives/alert/alertForm.html',
restrict: 'E',
scope: {
topic: '=topic',
description: '=description'
},
controller: function($scope) {
$scope.words = [];
this.showAlert = function() {
$scope.description.push("hello");
};
}
};
});
loginForm directive
angular.module('myApp')
.directive('loginForm', function() {
return {
templateUrl: 'app/directives/loginForm/loginForm.html',
restrict: 'E',
scope: {
successCallback: '&',
errorCallback: '&',
emailField: '='
},
link: function (scope, element, attrs) {
},
controller: function ($rootScope, $scope, authenticationService) {
$scope.loginFormData = {};
$scope.inProgress = false;
$scope.onLogin = function (form) {
if (form.$valid) {
$scope.inProgress = true;
authenticationService.loginUser('password', $scope.loginFormData).then(function () {
$scope.successCallback({formData: $scope.loginFormData});
}, function (err) {
$scope.inProgress = false;
if (err.message) {
**// i want to call here**
}
});
}
}
}
};
});
You can use require config of directive.
When a directive requires a controller, it receives that controller as
the fourth argument of its link function. Ref : Documentation
You can implement this in your code
angular.module(‘myApp')
.directive('loginForm', function() {
return {
templateUrl: 'app/directives/loginForm/loginForm.html',
restrict: 'E',
require:'alertForm',
scope: {
successCallback: '&',
errorCallback: '&',
emailField: '='
},
link: function (scope, element, attrs, alertFormCtrl) {
scope.alertFormCtrl = alertFormCtrl;
},
controller: function ($rootScope, $scope, authenticationService) {
$scope.loginFormData = {};
$scope.inProgress = false;
$scope.onLogin = function (form) {
if (form.$valid) {
$scope.inProgress = true;
authenticationService.loginUser('password', $scope.loginFormData).then(function () {
$scope.successCallback({formData: $scope.loginFormData});
}, function (err) {
$scope.inProgress = false;
if (err.message) {
// Calling showAlert function of alertFormCtrl
$scope.alertFormCtrl.showAlert();
}
});
}
}
}
};
});
Add the following line in the app/directives/loginForm/loginForm.html :
<alertForm topic="something" description = "something" ng-if="showAlert"></alertForm>
Now inside the loginForm directive's controller : // i want to call here
use
$scope.showAlert = true;
Note: you can use some variable to setup the topic and description as well inside the alertForm.
I want to use the Controller As syntax in my Angular directives for two reasons. It's more plain JS and there's no dependency on the $scope service which will not be available in Angular 2.0.
It works great for a single directive but I cannot figure out how to print a property from the controller of a parent directive in a child directive.
function parentCtrl () {
this.greeting = { hello: 'world' };
}
function childCtrl () {}
angular.module('app', [])
.controller('parentCtrl', parentCtrl)
.controller('childCtrl', childCtrl)
.directive('myParent', function () {
return {
scope: {},
bindToController: true,
controller: 'parentCtrl',
controllerAs: 'parent',
template: '<my-child></my-child>'
}
})
.directive('myChild', function () {
return {
scope: {
greeting: '='
},
bindToController: true,
controller: 'childCtrl',
controllerAs: 'child',
template: '<p>{{ greeting.hello }}</p>'
}
});
You have to require the parent controller, the use the link function to inject the parent to the child. The myChild directive would become:
.directive('myChild', function () {
return {
scope: {
// greeting: '=' // NO NEED FOR THIS; USED FROM PARENT
},
bindToController: true, // UNNECESSARY HERE, THERE ARE NO SCOPE PROPS
controller: 'childCtrl',
controllerAs: 'child',
template: '<p>{{ child.greeting.hello }}</p>', // PREFIX WITH VALUE
// OF `controllerAs`
require: ['myChild', '^myParent'],
link: function(scope, elem, attrs, ctrls) {
var myChild = ctrls[0], myParent = ctrls[1];
myChild.greeting = myParent.greeting;
}
}
});
I found that you can use element attributes to pass properties from the parent directive controller's scope to a child.
function parentCtrl () {
this.greeting = 'Hello world!';
}
function myParentDirective () {
return {
scope: {},
controller: 'parentCtrl',
controllerAs: 'ctrl',
template: '<my-child greeting="ctrl.greeting"></my-child>'
}
}
function childCtrl () {}
function myChildDirective () {
return {
scope: {
greeting: '='
},
bindToController: true,
controller: 'childCtrl',
controllerAs: 'ctrl',
template: '<p>{{ ctrl.greeting }}</p><input ng-model="ctrl.greeting" />'
}
}
angular.module('parent', [])
.controller('parentCtrl', parentCtrl)
.directive('myParent', myParentDirective);
angular.module('child', [])
.controller('childCtrl', childCtrl)
.directive('myChild', myChildDirective);
angular.module('app', ['parent', 'child']);