ng-model for `<input type=“file”/>` (with directive DEMO)

后端 未结 12 2263
北恋
北恋 2020-11-21 06:40

I tried to use ng-model on input tag with type file:


But after selecting a file, in

12条回答
  •  爱一瞬间的悲伤
    2020-11-21 06:58

    If you want something a little more elegant/integrated, you can use a decorator to extend the input directive with support for type=file. The main caveat to keep in mind is that this method will not work in IE9 since IE9 didn't implement the File API. Using JavaScript to upload binary data regardless of type via XHR is simply not possible natively in IE9 or earlier (use of ActiveXObject to access the local filesystem doesn't count as using ActiveX is just asking for security troubles).

    This exact method also requires AngularJS 1.4.x or later, but you may be able to adapt this to use $provide.decorator rather than angular.Module.decorator - I wrote this gist to demonstrate how to do it while conforming to John Papa's AngularJS style guide:

    (function() {
        'use strict';
    
        /**
        * @ngdoc input
        * @name input[file]
        *
        * @description
        * Adds very basic support for ngModel to `input[type=file]` fields.
        *
        * Requires AngularJS 1.4.x or later. Does not support Internet Explorer 9 - the browser's
        * implementation of `HTMLInputElement` must have a `files` property for file inputs.
        *
        * @param {string} ngModel
        *  Assignable AngularJS expression to data-bind to. The data-bound object will be an instance
        *  of {@link https://developer.mozilla.org/en-US/docs/Web/API/FileList `FileList`}.
        * @param {string=} name Property name of the form under which the control is published.
        * @param {string=} ngChange
        *  AngularJS expression to be executed when input changes due to user interaction with the
        *  input element.
        */
        angular
            .module('yourModuleNameHere')
            .decorator('inputDirective', myInputFileDecorator);
    
        myInputFileDecorator.$inject = ['$delegate', '$browser', '$sniffer', '$filter', '$parse'];
        function myInputFileDecorator($delegate, $browser, $sniffer, $filter, $parse) {
            var inputDirective = $delegate[0],
                preLink = inputDirective.link.pre;
    
            inputDirective.link.pre = function (scope, element, attr, ctrl) {
                if (ctrl[0]) {
                    if (angular.lowercase(attr.type) === 'file') {
                        fileInputType(
                            scope, element, attr, ctrl[0], $sniffer, $browser, $filter, $parse);
                    } else {
                        preLink.apply(this, arguments);
                    }
                }
            };
    
            return $delegate;
        }
    
        function fileInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {
            element.on('change', function (ev) {
                if (angular.isDefined(element[0].files)) {
                    ctrl.$setViewValue(element[0].files, ev && ev.type);
                }
            })
    
            ctrl.$isEmpty = function (value) {
                return !value || value.length === 0;
            };
        }
    })();
    

    Why wasn't this done in the first place? AngularJS support is intended to reach only as far back as IE9. If you disagree with this decision and think they should have just put this in anyway, then jump the wagon to Angular 2+ because better modern support is literally why Angular 2 exists.

    The issue is (as was mentioned before) that without the file api support doing this properly is unfeasible for the core given our baseline being IE9 and polyfilling this stuff is out of the question for core.

    Additionally trying to handle this input in a way that is not cross-browser compatible only makes it harder for 3rd party solutions, which now have to fight/disable/workaround the core solution.

    ...

    I'm going to close this just as we closed #1236. Angular 2 is being build to support modern browsers and with that file support will easily available.

提交回复
热议问题