У меня много входных файлов, и для каждого входного файла у меня есть предварительный div.
Входной файл принимает только изображения, поэтому, когда я выбираю какое-то изображение, я могу его просмотреть в предварительном div.
Я хочу также, когда я выбираю какое-то изображение для создания области для него динамически, я имею в виду, например, если у меня есть этот входной файл:
<input id="identityDocument" name="identityDocument"
ui-jq="filestyle" type="file" class="filestyle input-lg" ui-options="{
buttonText: '{{'ACTIONS.UPLOAD' | translate}}',
iconName: 'fa fa-inbox'
}"
accept="image/*">
Я хочу создать переменную для нее, которая вызвала: $scope.candidature.identityDocument
Эта переменная области будет содержать только имя выбранного изображения, чтобы сохранить его в базе данных.
Я хочу использовать другую переменную scope, которая будет содержать данные изображения, поэтому я могу просмотреть ее после события onchange
.
Еще одна вещь, которую я хочу, - получить требуемую работу над входным файлом, так как нет поддержки type="file"
ввода type="file"
с помощью службы ng-model
.
Я сделал все это, и он работает следующим образом:
это мой html-код для одного ввода:
<div class="row">
<div class="form-group col-md-4">
<label for="identityDocument">{{'FME_CANDIDATURE.PERSONAL_INFORMATIONS.IDENTITY_DOCUMENT' |
translate}}: </label>
<input id="identityDocument" name="identityDocument"
ui-jq="filestyle" type="file" class="filestyle input-lg" ui-options="{
buttonText: '{{'ACTIONS.UPLOAD' | translate}}',
iconName: 'fa fa-inbox'
}"
onchange="angular.element(this).scope().setFile(this,'identityDoc')"
accept="image/*">
<p class="help-block" style="color: #ff635d; !important;">
<span ng-show="step1.identityDocument.$invalid && !step1.identityDocument.$pristine">{{'FME_CANDIDATURE.PERSONAL_INFORMATIONS.IDENTITY_DOCUMENT_ERROR' | translate}}</span>
</p>
</div>
<div class="form-group col-md-4 mb-0">
<h4 class="custom-font text-greensea"><strong>{{'ACTIONS.PREVIEW' | translate}}</strong></h4>
<div><img ng-src="{{identityDoc}}" class="md-card-image img-responsive img-thumbnail"
alt="{{'ERRORS.NO_PHOTO_SELECTED' | translate}}"></div>
</div>
</div>
в этом коде у меня есть входной файл, который принимает только изображения, и когда я выбираю какое-то изображение, я вызываю функцию setFile()
, эта функция будет принимать два аргумента, текущий вход и имя, которое я хочу передать в его область (так как ng- модель не работает). и у меня есть еще один div, который будет содержать img
для предварительного просмотра выбранного изображения.
И это код функции setFile()
:
$scope.setFile = function(element, name) {
$scope.currentFile = element.files[0];
let reader = new FileReader();
reader.onload = function(event) {
//Converts Angular expression into a function, in our case we convert
//the string we passed as a variable
//and then assign a value to the parsed string
$parse(name).assign($scope, event.target.result);
//the same as above but instead we passing the name of selected image to the candidature object
$parse('candidature.'+name).assign($scope, element.value.replace(/^.*[\\\/]/, ''));
$scope.$apply();
};
// when the file is read it triggers the onload event above.
reader.readAsDataURL(element.files[0]);
};
так что функция принимает входные данные и строку, в этом примере HTML я передаю второй параметр как "identityDocument"
, эта функция затем создаст переменную с именем: $scope.identityDocument
которая будет содержать данные изображения для предварительного просмотра и $scope.candidature.identityDocument
который будет содержать имя изображения.
для выполнения необходимых работ для этого входного файла я использовал эту директиву:
app.directive('validFile',function(){
return {
require:'ngModel',
link:function(scope,el,attrs,ngModel){
//change event is fired when file is selected
el.bind('change',function(){
scope.$apply(function(){
ngModel.$setViewValue(el.val());
ngModel.$render();
});
});
}
}
});
следующим образом:
<input ... accept="image/*" valid-file required>
В настоящее время этот код работает отлично, но я должен использовать директиву и функцию в контроллере, мой вопрос: не могу ли я использовать только одну директиву, которая может делать все это без использования этой функции контроллера?
Я добавил эту строку $parse(name+'Upload').assign($scope, element.files[0]);
к функции setFile
, которую я использую для загрузки файла следующим образом:
let file = $scope.identityDocUpload;
let fd = new FormData();
fd.append('file', file);
$http.post('http://localhost:8080/fileUpload', fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function () {
})
.error(function () {
});
Я бы предложил что-то вроде
(function () {
'use strict';
angular
.module('myApp')
.directive('validFile', validFile);
validFile.$inject = [];
function validFile() {
var directive = {
link: link,
controller: ValidFileController,
scope: {
fileRead: '=',
}
};
ValidFileController.$inject = ['$scope'];
return directive;
function link(scope, element, attrs, controller) {
// do UI-things
}
function ValidFileController($scope){
/* jshint validthis: true */
var vm = this;
// do controller things
}
}
})();
Это директива с контроллером. В этом случае вы можете выполнить всю свою логику в рамках одной директивы и не нуждаться в ng-controller
.
Эта ng-model
не работает для input type="file"
прав, но ваш совершенный код не очень велик, потому что вы получаете доступ к области $scope
в html через атрибут html.
Таким образом, ваша техника загрузки может быть заменена
element.bind('change', function (changeEvent) {
var reader = new FileReader();
reader.onload = function (loadEvent) {
scope.$apply(function () {
scope.fileRead = loadEvent.target.result;
});
}
reader.readAsDataURL(changeEvent.target.files[0]);
});
Для ваших динамических значений модели вы можете выбирать между различными подходами, fe
$scope['yourAttributeName'] = value;
или
var the_string = 'my.test';
var model = $parse(the_string);
model.assign($scope, 'test');