The solution I'll provide here is based on the post here:
Creating a Blob from a base64 string in JavaScript
I faced similar case, but the images are stored on the server using Base64.When the web page is loaded, and the images are retrieved from the Database, such images must be added back to the flow.files
array. The images are saved in Database using Base64 string. So, during page load, the only way for me was to convert Base64 string to Blob and add the files back to the flow.files
array.
This enabled the flow controller to function correctly after the page is loaded from the Database.
Following are the steps:
Add directive load-photo
and add it to the input element additional_image1
which has the Base64 string loaded from Database on document ready event using jQuery.
Add a Directive to access the element and call scope function $scope.loadPhoto
on document ready to load the photo.
In load photo function, convert the Base64 to Blob and add the file to the flow control.
Ensure the scope variable $scope.imageStringB64
and the input element additional_image1
are synchronized manually as ng-model
didn't work as expected. This is because jQuery code outside angular is loading the input element from Database, and I found out that they are not bound dynamically.
JavaScript code:
app.directive('loadPhoto', function () {
return function (scope, element, attrs) {
//This directive 'load-photo' is required to access the DOM element inside the scope
//This will get the Base64 string of the image which is stored in the input element
angular.element(document).ready(function () {
scope.loadPhoto(element[0]);
})
}
})
app.controller('photosController', ['$scope', '$http', '$timeout',
function ($scope, $http, $timeout) {
...
var BLANK_IMG_URL = "//:0";
$scope.removeFile = function () {
//debugger;
$scope.$flow.cancel();
$scope.imageStringB64 = '';
$scope.imageString = BLANK_IMG_URL;
}
$scope.loadPhoto = function (elem) {
//Load photo from Database
//The photo Base64 is stored in the input element 'elem'
var blobImage;
var tmpBase64;
tmpBase64 = angular.element(elem).val();
if (tmpBase64) {
//Convert Base64 to Blob object
blobImage = b64toBlob(tmpBase64, 'image/png');
blobImage.name = "image.png";
//Add the Blob object to flow files.
$scope.$flow.addFile(blobImage);
}
}
...
}]);
HTML Code:
<div class="photo-wrapper" ng-controller="photosController"
flow-init
flow-file-added="!isAppraiserSigned() && !!{png:1,gif:1,jpg:1,jpeg:1}[$file.getExtension()]"
flow-files-submitted="$flow.upload()">
<h4 class='photo-title'>Photo 1</h4>
<div class="property-photo drag-drop-photo" ng-hide="$flow.files.length" flow-drop
flow-drag-enter="isAppraiserSigned()?style={}:style={border:'4px solid green'}" flow-drag-leave="style={}" ng-style="style">
<div class='drag-drop-lbl'>Drop file here</div>
</div>
<div class="property-photo" flow-drop ng-show="$flow.files.length"
flow-drag-enter="isAppraiserSigned()?style={}:style={border:'4px solid green'}" flow-drag-leave="style={}" ng-style="style">
<img id="additional_image1_section" style="max-height:100%" flow-img="$flow.files[0]" />
<input id="additional_image1" name = "additional_image1" ng-hide="true" type="text" ng-model="imageStringB64" load-photo/>
</div>
<div>
<a href="#" class="btn" ng-hide="$flow.files.length" flow-btn flow-attrs="{accept:'image/*'}"><%=selectImageLbl%></a>
<a href="#" class="btn" ng-show="$flow.files.length" flow-btn flow-attrs="{accept:'image/*'}">Change</a>
<a href="#" class="btn btn-danger" ng-show="$flow.files.length"
ng-click="removeFile()">
Remove
</a>
</div>
<div class='photo-description'>
<label class='description-lbl' for='additional_image_describe1'><%=descriptionLbl%></label>
<input class='description' id='additional_image_describe1' name='additional_image_describe1' type="text" />
</div>
</div>
See this code sample for more options to convert Base64 image to blob and back to Base64:
fiddle.jshell.ne