James N James N - 4 months ago 266
AngularJS Question

angular material modal and ng-file-upload

I am working on image upload using angular material, ng-file-upload, and ng-imgcrop-extended. I was previously using all of this on a normal page, and everything was working fine, but requirements have changed and I had to move this logic to a modal.

The way it works is I am using

ng-imgcrop
to crop the photos, and
ng-file-upload
does the uploading. So right now, I have an element listening to the file select, and that handles the cropping. Right now however, it is not listening to the file select, and I can only reason that is from the modal.

Here is my code

modal render

$scope.headshotModal = function(ev) {
var useFullScreen;
useFullScreen = ($mdMedia('sm') || $mdMedia('xs')) && $scope.customFullscreen;
$mdDialog.show({
locals: {
p: $scope.persona
},
controller: 'ImagesController',
templateUrl: 'application/views/images/image_modal.html',
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose: true,
fullscreen: useFullScreen
}).then((function(answer) {
$scope.status = 'You said the information was "' + answer + '".';
}), function() {
$scope.status = 'You cancelled the dialog.';
});
$scope.$watch((function() {
return $mdMedia('xs') || $mdMedia('sm');
}), function(wantsFullScreen) {
$scope.customFullscreen = wantsFullScreen === true;
});
};


images_controller

angular.module('App').controller('ImagesController', [
'$scope', 'p', '$mdDialog', 'ImageService', '$routeParams', function($scope, p, $mdDialog, ImageService, $routeParams) {
var handleFileSelect;
$scope.persona = p;
$scope.uploadedImg = false;
$scope.myCroppedImage = '';
$scope.myImage = '';
$scope.blockingObject = {
block: true
};
$scope.callTestFuntion = function() {
$scope.blockingObject.render(function(dataURL) {
$scope.showRender = true;
console.log('via render');
console.log(dataURL.length);
});
};
$scope.blockingObject.callback = function(dataURL) {
console.log('via function');
console.log(dataURL.length);
};
handleFileSelect = function(evt) {
var file, reader;
file = evt.currentTarget.files[0];
console.log(file);
$scope.uploadedImg = true;
reader = new FileReader;
reader.onload = function(evt) {
$scope.$apply(function($scope) {
$scope.myImage = evt.target.result;
});
};
reader.readAsDataURL(file);
};
angular.element(document.querySelector('#imgInput')).on('change', function() {
console.log('handlefileselect');
// this function runs the code needed. it is not being triggered
handleFileSelect;
});
$scope.thenRedirect = function() {
return window.location.href = "personas/" + $scope.persona.slug;
};
$scope.testCrop = function(file) {
ImageService.uploadCroppedImg(file, 'headshot', $routeParams, $scope.cropAttributes);
return $scope.thenRedirect();
};
$scope.cancel = function() {
$scope.uploadedImg = false;
return $scope.showRender = false;
};
$scope.hide = function() {
$mdDialog.hide();
};
return $scope.cancelOut = function() {
$mdDialog.cancel();
};
}
]);


modal.slim

md-dialog.fs [style="width: 100%; margin-left:25%; margin-right: 25%;" aria-label=("Image Edit") ng-cloak=""]
/form
md-toolbar.text-center
.md-toolbar-tools
h2 Image Edit
span flex=""
md-button.md-icon-button [ng-click="cancelOut()" aria-label="Cancel"]
i.fa.fa-times
md-dialog-content
.md-dialog-content
h2.text-center Edit Your Headshot

div.input-div
| Select an image file:
input#imgInput [type="file" ngf-select accept="image/*" ng-model="headshotFile"] /
/ [ng-show='uploadedImg']
div
md-button.render-btn[ng-click="callTestFuntion()"] Render
.crop-area
img-crop cropject='cropAttributes' area-type="rectangle" image="myImage" live-view="blockingObject" result-image="myCroppedImage"

a.img-upload [href="#" ngf-select="uploadBanner($file)" ngf-dimensions="$width > 149 && $height > 149"]
i.fa.fa-camera
span Banner

a.img-upload[style='cursor: pointer;'ng-click="testCrop(headshotFile)"]
i.fa.fa-upload
span Upload

a.cancel-img.img-upload [href="#" ng-click="cancel()"]
i.fa.fa-ban
span Cancel


this code works on a normal html page. But the problem seems to be it cannot listen to the
angular.element(document.querySelector('#imgInput')).on('change')
part of the
ImagesController
. does anyone know how using a modal, I can handle these types of events? I have seen that I might have to wrap some logic in the
$mdDialog.show().resolve()
function, but i'm not sure what it's expecting.

Any help would be appreciated :)

Answer

Based on your results, I would approach this problem by wiring up the event in the onShowing or onComplete event for the dialog. I would create a callback function here:

$mdDialog.show({
    locals: {
      p: $scope.persona
    },
    controller: 'ImagesController',
    templateUrl: 'application/views/images/image_modal.html',
    parent: angular.element(document.body),
    targetEvent: ev,
    clickOutsideToClose: true,
    fullscreen: useFullScreen,
    onComplete: wireUpChangeEvent,
    onRemoving: removeChangeEvent // so it doesn't get wired up multiple times
  })

I'm not 100%, but I think the dialog stays on the DOM after you hide(close) it. If that's the case, you either need the onRemoving event function or a check to see if it's already been wired up to prevent multiple firings. The function would be called from the controller that launches the dialog. You may need to make the two of them share the same scope by using the scope option and telling it to preserveScope. I'm also not sure if the template will be loaded and on the DOM the first time onShowing is called, so it's probably safer to use onComplete.

Comments