Je suis nouveau à angular. J'essaie de lire le chemin du fichier téléchargé à partir du champ 'fichier' HTML chaque fois qu'un 'changement' se produit sur ce champ. Si j'utilise 'onChange' cela fonctionne mais quand je l'utilise de façon angulaire en utilisant 'ng-change' cela ne fonctionne pas.
<script>
var DemoModule = angular.module("Demo",[]);
DemoModule .controller("form-cntlr",function($scope){
$scope.selectFile = function()
{
$("#file").click();
}
$scope.fileNameChaged = function()
{
alert("select file");
}
});
</script>
<div ng-controller="form-cntlr">
<form>
<button ng-click="selectFile()">Upload Your File</button>
<input type="file" style="display:none"
id="file" name='file' ng-Change="fileNameChaged()"/>
</form>
</div>
NomFichierChagé () n'appelle jamais. Firebug ne montre pas non plus d'erreur.
Pas de support de liaison pour le contrôle de téléchargement de fichier
https://github.com/angular/angular.js/issues/1375
<div ng-controller="form-cntlr">
<form>
<button ng-click="selectFile()">Upload Your File</button>
<input type="file" style="display:none"
id="file" name='file' onchange="angular.element(this).scope().fileNameChanged(this)" />
</form>
</div>
au lieu de
<input type="file" style="display:none"
id="file" name='file' ng-Change="fileNameChanged()" />
peux-tu essayer
<input type="file" style="display:none"
id="file" name='file' onchange="angular.element(this).scope().fileNameChanged()" />
Remarque: cela nécessite que l'application angular soit toujours en mode débogage . Cela ne fonctionnera pas dans le code de production si le mode débogage est désactivé.
et dans vos changements de fonction au lieu de
$scope.fileNameChanged = function() {
alert("select file");
}
peux-tu essayer
$scope.fileNameChanged = function() {
console.log("select file");
}
Vous trouverez ci-dessous un exemple pratique de téléchargement de fichier avec glisser-déposer. Le téléchargement de fichier peut être utile http://jsfiddle.net/danielzen/utp7j/
Informations sur le téléchargement de fichier angulaire
URL pour le téléchargement de fichier AngularJS dans ASP.Net
http://cgeers.com/2013/05/03/angularjs-file-upload/
AngularJs upload natif multi-fichiers avec des progrès avec NodeJS
http://jasonturim.wordpress.com/2013/09/12/angularjs-native-multi-file-upload-with-progress/
ngUpload - Un service AngularJS pour le téléchargement de fichiers à l'aide d'iframe
J'ai fait une petite directive d'écouter les modifications apportées aux entrées de fichier.
view.html:
<input type="file" custom-on-change="uploadFile">
controller.js:
app.controller('myCtrl', function($scope){
$scope.uploadFile = function(event){
var files = event.target.files;
};
});
directive.js:
app.directive('customOnChange', function() {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var onChangeHandler = scope.$eval(attrs.customOnChange);
element.on('change', onChangeHandler);
element.on('$destroy', function() {
element.off();
});
}
};
});
Ceci est un raffinement de certains des autres autour, les données se retrouveront dans un modèle ng, qui est normalement ce que vous voulez.
Balisage (créez simplement un fichier de données d'attribut pour que la directive puisse le trouver)
<input
data-file
id="id_image" name="image"
ng-model="my_image_model" type="file">
JS
app.directive('file', function() {
return {
require:"ngModel",
restrict: 'A',
link: function($scope, el, attrs, ngModel){
el.bind('change', function(event){
var files = event.target.files;
var file = files[0];
ngModel.$setViewValue(file);
$scope.$apply();
});
}
};
});
La méthode la plus simple consiste à écrire votre propre directive pour la lier à l'événement "change" . Juste pour vous informer que IE9 ne prend pas en charge FormData, vous ne pouvez donc pas obtenir l'objet fichier à partir de l'événement change.
Vous pouvez utiliser ng-file-upload library qui prend déjà en charge IE avec FileAPI polyfill et simplifier la publication du fichier sur le serveur. Il utilise une directive pour y parvenir.
<script src="angular.min.js"></script>
<script src="ng-file-upload.js"></script>
<div ng-controller="MyCtrl">
<input type="file" ngf-select="onFileSelect($files)" multiple>
</div>
JS:
//inject angular file upload directive.
angular.module('myApp', ['ngFileUpload']);
var MyCtrl = [ '$scope', 'Upload', function($scope, Upload) {
$scope.onFileSelect = function($files) {
//$files: an array of files selected, each file has name, size, and type.
for (var i = 0; i < $files.length; i++) {
var $file = $files[i];
Upload.upload({
url: 'my/upload/url',
data: {file: $file}
}).then(function(data, status, headers, config) {
// file is uploaded successfully
console.log(data);
});
}
}
}];
J'ai développé l'idée de @Stuart Axon d'ajouter une liaison bidirectionnelle pour l'entrée de fichier (c'est-à-dire, autoriser la réinitialisation de l'entrée en réinitialisant la valeur du modèle sur null):
app.directive('bindFile', [function () {
return {
require: "ngModel",
restrict: 'A',
link: function ($scope, el, attrs, ngModel) {
el.bind('change', function (event) {
ngModel.$setViewValue(event.target.files[0]);
$scope.$apply();
});
$scope.$watch(function () {
return ngModel.$viewValue;
}, function (value) {
if (!value) {
el.val("");
}
});
}
};
}]);
Semblable à certaines des autres bonnes réponses ici, j'ai écrit une directive pour résoudre ce problème, mais cette mise en œuvre reflète plus étroitement la manière angulaire d'attacher des événements.
Vous pouvez utiliser la directive comme ceci:
HTML
<input type="file" file-change="yourHandler($event, files)" />
Comme vous pouvez le constater, vous pouvez injecter les fichiers sélectionnés dans votre gestionnaire d’événements, comme vous injecteriez un objet $ event dans n’importe quel gestionnaire d’événements ng.
Javascript
angular
.module('yourModule')
.directive('fileChange', ['$parse', function($parse) {
return {
require: 'ngModel',
restrict: 'A',
link: function ($scope, element, attrs, ngModel) {
// Get the function provided in the file-change attribute.
// Note the attribute has become an angular expression,
// which is what we are parsing. The provided handler is
// wrapped up in an outer function (attrHandler) - we'll
// call the provided event handler inside the handler()
// function below.
var attrHandler = $parse(attrs['fileChange']);
// This is a wrapper handler which will be attached to the
// HTML change event.
var handler = function (e) {
$scope.$apply(function () {
// Execute the provided handler in the directive's scope.
// The files variable will be available for consumption
// by the event handler.
attrHandler($scope, { $event: e, files: e.target.files });
});
};
// Attach the handler to the HTML change event
element[0].addEventListener('change', handler, false);
}
};
}]);
Cette directive transmet également les fichiers sélectionnés:
/**
*File Input - custom call when the file has changed
*/
.directive('onFileChange', function() {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var onChangeHandler = scope.$eval(attrs.onFileChange);
element.bind('change', function() {
scope.$apply(function() {
var files = element[0].files;
if (files) {
onChangeHandler(files);
}
});
});
}
};
});
Le HTML, comment l'utiliser
<input type="file" ng-model="file" on-file-change="onFilesSelected">
Dans mon contrôleur:
$scope.onFilesSelected = function(files) {
console.log("files - " + files);
};
Je recommande de créer une directive
<input type="file" custom-on-change handler="functionToBeCalled(params)">
app.directive('customOnChange', [function() {
'use strict';
return {
restrict: "A",
scope: {
handler: '&'
},
link: function(scope, element){
element.change(function(event){
scope.$apply(function(){
var params = {event: event, el: element};
scope.handler({params: params});
});
});
}
};
}]);
cette directive peut être utilisée plusieurs fois, elle utilise sa propre portée et ne dépend pas de la portée parent. Vous pouvez également donner des paramètres à la fonction de gestionnaire. La fonction de gestionnaire sera appelée avec l'objet scope, qui était actif lorsque vous avez modifié l'entrée. $ apply met à jour votre modèle chaque fois que l'événement change est appelé
La version angulaire jqLite la plus simple.
JS:
.directive('cOnChange', function() {
'use strict';
return {
restrict: "A",
scope : {
cOnChange: '&'
},
link: function (scope, element) {
element.on('change', function () {
scope.cOnChange();
});
}
};
});
HTML:
<input type="file" data-c-on-change="your.functionName()">
ng-change
1Pour qu'un élément <input type=file>
fonctionne avec la directive ng-change , il faut une directive custom qui fonctionne avec la directive ng-model .
<input type="file" files-input ng-model="fileList"
ng-change="onInputChange()" multiple />
angular.module("app",[])
.directive("filesInput", function() {
return {
require: "ngModel",
link: function postLink(scope,elem,attrs,ngModel) {
elem.on("change", function(e) {
var files = elem[0].files;
ngModel.$setViewValue(files);
})
}
}
})
.controller("ctrl", function($scope) {
$scope.onInputChange = function() {
console.log("input change");
};
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="ctrl">
<h1>AngularJS Input `type=file` Demo</h1>
<input type="file" files-input ng-model="fileList"
ng-change="onInputChange()" multiple />
<h2>Files</h2>
<div ng-repeat="file in fileList">
{{file.name}}
</div>
</body>
Les éléments angulaires (tels que l'élément racine d'une directive) sont des objets jQuery [Lite]. Cela signifie que nous pouvons enregistrer l'auditeur d'événement de la manière suivante:
link($scope, $el) {
const fileInputSelector = '.my-file-input'
function setFile() {
// access file via $el.find(fileInputSelector).get(0).files[0]
}
$el.on('change', fileInputSelector, setFile)
}
C'est la délégation d'événements jQuery. Ici, l'auditeur est attaché à l'élément racine de la directive. Lorsque l'événement est déclenché, il est affiché dans l'élément enregistré et jQuery détermine si l'événement provient d'un élément interne correspondant au sélecteur défini. Si c'est le cas, le gestionnaire va tirer.
Les avantages de cette méthode sont:
ng-if
ou ng-switch
)Je l'ai fait comme ça;
<!-- HTML -->
<button id="uploadFileButton" class="btn btn-info" ng-click="vm.upload()">
<span class="fa fa-Paperclip"></span></button>
<input type="file" id="txtUploadFile" name="fileInput" style="display: none;" />
// self is the instance of $scope or this
self.upload = function () {
var ctrl = angular.element("#txtUploadFile");
ctrl.on('change', fileNameChanged);
ctrl.click();
}
function fileNameChanged(e) {
console.log(self.currentItem);
alert("select file");
}
Vous pouvez simplement ajouter le code ci-dessous dans onchange et il détectera le changement. vous pouvez écrire une fonction sur X click ou quelque chose pour supprimer les données du fichier.
document.getElementById(id).value = "";
Solution trop complète basée sur:
`onchange="angular.element(this).scope().UpLoadFile(this.files)"`
Un moyen simple de masquer le champ de saisie et de le remplacer par une image, ici après une solution, qui nécessite également un piratage angulaire mais qui fait l'affaire [TriggerEvent ne fonctionne pas comme prévu]
La solution:
Lorsque vous cliquez sur l'image, simulez une action DOM. Cliquez sur le champ de saisie. Et voilà!
var tmpl = '<input type="file" id="{{name}}-filein"' +
'onchange="angular.element(this).scope().UpLoadFile(this.files)"' +
' multiple accept="{{mime}}/*" style="display:none" placeholder="{{placeholder}}">'+
' <img id="{{name}}-img" src="{{icon}}" ng-click="clicked()">' +
'';
// Image was clicked let's simulate an input (file) click
scope.inputElem = elem.find('input'); // find input in directive
scope.clicked = function () {
console.log ('Image clicked');
scope.inputElem[0].click(); // Warning Angular TriggerEvent does not work!!!
};
Un autre moyen intéressant d’écouter les modifications d’entrée dans le fichier consiste à surveiller l’attribut ng-model du fichier d’entrée. Bien sûr, FileModel est une directive personnalisée.
Comme ça:
HTML -> <input type="file" file-model="change.fnEvidence">
Code JS ->
$scope.$watch('change.fnEvidence', function() {
alert("has changed");
});
J'espère que ça peut aider quelqu'un.