Working with modals in angularjs - javascript

I've got this piece of code here
<div ng-repeat="item in items" class="col-sm-4 portfolio-item">
<script type="text/ng-template" id="myModalContent.html">
However, I can't access {{item}} within the script tags. Is there a way I can insert id and type from outside the div tags? Sorry for the newbie question.
Here is the code for the controller:
.controller('listCtrl', function($scope, $modal, $log, $stateParams, items) {
$scope.animationsEnabled = true;
$scope.open = function(size) {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
item: function() {
return $scope.item;
}
}
});
modalInstance.result.then(function(selectedItem) {
$scope.selected = selectedItem;
}, function() {
$log.info('Modal dismissed at: ' + new Date());
});
};
$scope.toggleAnimation = function() {
$scope.animationsEnabled = !$scope.animationsEnabled;
};
})
// Please note that $modalInstance represents a modal window (instance) dependency.
// It is not the same as the $modal service used above.
.controller('ModalInstanceCtrl', function($scope, $modalInstance, items) {
$scope.items = items;
$scope.selected = {
items: $scope.items
};
$scope.ok = function() {
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
})

You can't access item object in modal template because it's compiled in isolated scope child of the $rootScope, so there is not way for modal contents to inherit items.
What you want to do is to provide a base scope for the modal instance. Try this:
var modalInstance = $modal.open({
scope: $scope, // <--- use this scope as the base for new scope
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
item: function() {
return $scope.item;
}
}
});
In above snippet, modal service will create new child scope from the passed $scope, in which case modal scope will inherit prototypically items objects.

Related

crop doesn't work inside bootstrap modal

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.

Using $uibModalInstance in directive

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.

AngularJS: pass variable to modal

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

Angular unit test

I am extends bootstrap modal like this:
.directive("modal", [function(){
var controller = function($scope, $attrs, $element, $uibModal){
var defaultOptions = {
title: "Modal title",
content: "Modal body",
controller: "DefaultModalController",
templateUrl: "js/dev/shared/directives/templates/default-modal-template.html"
};
$element.on($scope.event, function(){
var userOptions = {
title: $attrs.title,
content: $attrs.content,
templateUrl: $attrs.templateUrl,
controller: $attrs.controller
};
options = angular.extend({},defaultOptions, userOptions || {});
$uibModal.open({
templateUrl: options.templateUrl,
controller: options.controller,
resolve: {
options: function () {
return options
}
}
});
});
};
return {
restrict: "A",
scope: {
event: "#"
},
controller: ["$scope", "$attrs", "$element", "$uibModal", controller]
}
}])
.controller("DefaultModalController", ["$scope", "$modalInstance", "options",
function($scope, $modalInstance, options){
$scope.modalOptions = options;
$scope.close = function(){
$modalInstance.close();
}
}]);
and my test looks like this:
descr
ibe("ModalDirective", ()=>{
var element,
compile,
scope,
controller;
beforeEach(module("app.directive"));
beforeEach(inject((_$compile_, _$rootScope_, _$controller_)=>{
compile = _$compile_;
controller = _$controller_;
scope = _$rootScope_.$new();
element = angular.element("<button modal>test</button>")
}));
it("should create default modal window", ()=>{
element = compile(element)(scope);
console.error(element.html());
expect(true).toBeTruthy();
})
});
but when compile(element)(scope) is executing I've got this error:
TypeError: 'undefined' is not an object (evaluating 'd.indexOf')
at a (https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.min.js:179)
What should I do to fix it?
[ EDIT ]
I fixed this, the problem was in creating directive.
In directive definition I have:
scope: {
event: "#"
}
and my template was <button modal>test</button> when I changed it to <button modal event='click'>test</button> problem was solved.

How do i pass changing data into a modal?

I'm trying to pass a changing scope variable into a modal window. I'm having trouble allowing the variable to change once the modal is open. Currently I have the data being passed to a controller when the modal is opened:
scope.open = function (roomname, image) {
console.log("clicked modal");
console.log("roomName: " + roomname);
console.log("image: " + image);
scope.imageContents = image;
console.log("scope.imageContents: " + scope.imageContents);
scope.modalInstance = $modal.open({
animation: scope.animationsEnabled,
templateUrl: 'tpl/modal-template.tpl.html',
controller: 'ModalInstanceCtrl',
resolve: {
items: function () {
console.log("scope.imageContents in resolve: " + scope.imageContents);
return scope.imageContents;
},
compassHeading: function () {
console.log("scope.imageContents in resolve: " + scope.compassHeading);
return scope.compassHeading;
}
}
});
};
and my controller:
angular.module('TestApp').controller('ModalInstanceCtrl',function ($scope, $modalInstance, items, compassHeading) {
'use strict';
$scope.items = items;
$scope.selected = {
item: $scope.items
};
$scope.compassHeading = compassHeading;
});
The compass Heading variable is constantly being updated, so I am trying to get the compassHeading variable to show these changes in the modal.
You could use a service which has your variable along with other variables:
angular.module('TestApp')
.service('TestService', [function () {
return {
model: {
'compassHeading': null
}
};
}]);
And in your main controller, you could use it like:
angular.module('TestApp')
.controller('MainController', ['$scope', 'TestService', function ($scope, testService) {
$scope.model = testService.model;
...
}]);
And in your $modal controller, you could do the same:
angular.module('TestApp')
.controller('ModalInstanceCtrl', ['$scope', 'TestService', function ($scope, testService) {
$scope.model = testService.model;
}]);
Then, anytime the value of compassHeading needs to be changed, you could just change it using the normal: $scope.model.compassHeading = <some_value_here>;.
Also, the value of compassHeading, if changed outside the controllers, will also be changed inside the controllers, since the model object of the service is called by reference.

Categories

Resources