nikk wong nikk wong - 5 months ago 63
AngularJS Question

Returning scope items to parent scope with $mdDialog.show()

Yo! I have a controller which houses a bunch of items on its

$scope
. One of the scope items,
$scope.openDialog
opens a
$mdDialog
via
$mdDialog.show()
. The object passed into
$mdDialog.show
has a template which houses controls for uploading files via the
ng-file-upload
project, which you can read about here.

I would like it if the items uploaded in the dialog window would be available in the main controller after exiting out of the dialog window. I am not sure as to whether the controller for the dialog window should reference the main
myCtrl
controller or use its own, and how to take make uploaded files available to
myCtrl
.

Here is the angular code:

angular.module('app', ['ngMaterial', 'ngFileUpload'])
.controller('myCtrl', ['$scope', '$mdDialog', 'Upload', function($scope, $mdDialog, Upload) {
var tmpl = "<md-dialog>\n" +
"<md-dialog-content>\n" +
" <input type=\"text\" ng-model=\"username\"></br></br>\n" +
" <input type=\"checkbox\" ng-model=\"multiple\">upload multiple file</br></br>\n" +
" watching model:\n" +
" <div class=\"button\" ngf-select ng-model=\"files\" ngf-multiple=\"multiple\">Select File</div>\n" +
" on file change:\n" +
" <div class=\"button\" ngf-select ngf-change=\"upload($files)\" ngf-multiple=\"multiple\">Select File</div>\n" +
" Drop File:\n" +
" <div ngf-drop ngf-select ng-model=\"files\" class=\"drop-box\" \n" +
" ngf-drag-over-class=\"dragover\" ngf-multiple=\"true\" ngf-allow-dir=\"true\"\n" +
" accept=\"image/*,application/pdf\">Drop pdfs or images here or click to upload</div>\n" +
" <div ngf-no-file-drop>File Drag/Drop is not supported for this browser</div>\n" +
" Image thumbnail: <img ngf-src=\"files[0]\">\n" +
" Files:\n" +
" <ul>\n" +
" <li ng-repeat=\"f in files\" style=\"font:smaller\">{{f.name}}</li>\n" +
" </ul>\n" +
" Upload Log:\n" +
" <pre>{{log}}</pre>\n" +
"<md-action><div class=\"button\" ng-click=\"close()\">close!</div></md-action>\n" +
"<md-action><div class=\"button\" ng-click=\"upload()\">upload!</div></md-action>\n" +
"</md-dialog-content>\n" +
"</md-dialog>";
$scope.files = ['files should appear here', 'files 1', 'file2'];
$scope.openDialog = function () {
$mdDialog.show({
parent: angular.element(document.body),
template: tmpl,
controller: 'myCtrl'
});
};
$scope.close = function() {
$mdDialog.hide();
};
$scope.$watch('files', function () {
$scope.upload($scope.files);
});
$scope.upload = function (files) {
if (files && files.length) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
Upload.upload({
url: 'upload/url',
fields: {'username': $scope.username},
file: file
}).progress(function (evt) {
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
console.log('progress: ' + progressPercentage + '% ' + evt.config.file.name);
}).success(function (data, status, headers, config) {
console.log('file ' + config.file.name + 'uploaded. Response: ' + data);
});
}
}
};
}]);


BTW: As a housekeeping note, I often hear that application logic shouldn't be passed into a controller. In this situation, how would you move
$scope.upload
into a factory, given that it references
$scope
and
$scope
is not available in factories?

Thanks for the help.

Plnkr: http://plnkr.co/edit/e2MYdEABhj34ahtPTO0g?p=preview

Answer

You can pass the $scope of your controller to your $mdDialog as an example below

$mdDialog.show({
    parent: angular.element(document.body),
    template: tmpl,
    scope: $scope,
    controller: 'myCtrl'
});

Check plunkr : http://plnkr.co/edit/0hFWEyWdetTXcPLPkbmQ?p=preview

To move application logic to factory you will be doing something like this

$scope.upload = factory.upload(files,$scope.username); 

and factory will have method

 factory.upload = function(files,username)
 {
  function (files) {
    if (files && files.length) {
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
            Upload.upload({
                url: 'upload/url',
                fields: {'username': username},
                file: file
            }).progress(function (evt) {
                var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
                console.log('progress: ' + progressPercentage + '% ' + evt.config.file.name);
            }).success(function (data, status, headers, config) {
                console.log('file ' + config.file.name + 'uploaded. Response: ' + data);
            });
        }
    }
};