How to display base64 image in AngularJS - html

Need help again ;)
I would like to show a photo in my Angular page. These are my steps,
REST API gets a document/record from backend MongoDB. The base64 images are stored as this.
The images/data are loaded into an array {{file_src[i]}} in the component code, then the component HTML will show the image as below
Situations:
If I used "img srcs={{file_src[i]}}", I got insecure operation. My REST API server has CORS enabled. Since the image is base64 data and doesn't have any URL, I don't know it is related to CORS.
I googled around and found the ng-src and data-ng-src directives. Both of them don't work too. Please see my binding error below.
Question: how to show the base64 image in my Angular page?
------Code as requested by Vic--------
<section class="fhirForm">
<fieldset>
<legend class="hd">
<span class="text">Photo</span>
</legend>
<div class="bd" formArrayName="photos">
<div *ngFor="let photo of patFormGroup.controls.photos.controls; let i=index" class="panel panel-default">
<div class="panel-body" [formGroupName]="i">
<label>Description</label>
<input type="text" class="form-control" formControlName="desc">
<label>Photo</label>
<input type="file" size="30" multiple formControlName="photo" name="crud8" (change)="photoChange(input, i)" #input>
<!-- img src={{file_srcs[i]}} crossorigin="anonymous" alt="" /-->
<img data-ng-src={{file_srcs[i]}} alt="" />
<span class="glyphicon glyphicon-remove pull-right" *ngIf="patFormGroup.controls.photos.controls.length > 1" (click)="removePhoto(i)"></span>
</div>
</div>
</div>
</fieldset>
<div class="margin-20">
<a (click)="addPhoto()" style="cursor: default">
<small>Add another photo +</small>
</a>
</div>
</section>
initPhoto(desc?: String, photo?: string) {
//Add new entry on the 1 dimensional array. Allow 1 photo per section
this.file_srcs.push(photo);
console.log("Photo for file_srcs: [" + this.file_srcs[this.file_srcs.length - 1] + "]");
return this.formBuilder.group({
desc: [desc],
photo: [photo]
});
}
Please see the console.log. It showed that this.file_srcs are valid.
------------- Error Message in Chrome -------
------------- UPDATE 1 -----------
If I commented out the "input type=file ..." line above the "img src" as below, I can see the photo. What's wrong with my input? Sorry, I don't remember what is that #input for.
Hence, my issue may not be in the photo, but on the input line ;) Shame on me!!!
<label>Photo</label>
<!-- input type="file" size="30" formControlName="photo" name="crud8" (change)="photoChange(input, i)" #input -->
<img src={{file_srcs[i]}} crossorigin="anonymous" alt="" />
--------- RESOLVED -----------
Thanks a lot for all the help!!!
i. the base64 image isn't the root cause;
ii. the file input "input type=file" was initialized by incorrect supplying the base64 image as the default value. It caused the error - failed to set the value of HtmlInputElement is correct in IE. The error message 'Insecure Operation' may be misleading in Firefox.
Hence, the root cause is not related to the base64 image. I would like to delete this thread a week later.
initPhoto(desc?: String, photo?: string) {
this.file_srcs.push(photo);
console.log("Photo for file_srcs[" + (this.file_srcs.length - 1) + "]: [" + this.file_srcs[this.file_srcs.length - 1] + "]");
return this.formBuilder.group({
desc: [desc],
photo: [""] //This was photo: [photo]. After supplying the default value as "", it works well.
});
Best regards,
Autorun

Fetch the base64 content in your controller like this:
$http.get($scope.user.photo).then(function(response) {
$scope.user.data = response.data;
});
then display it on view
<img data-ng-src="data:image/png;base64,{{user.data}}"/>

I use base64 image a lot and haven't see that error before. Is it caused by the crossorigin attribute?
angular.module('test', []).controller('Test', Test);
function Test($scope) {
$scope.base64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAOCAYAAADwikbvAAAA+0lEQVQ4T6WS3W3CMBSFz40QvDJCu0GYALJB2QBeUFzjCm9AJ0gLMQl9STegG5QNYARG6CsI+SKjpmppSY3w8/10fnwIVzy6lE2SollrbBcAPV8ET2fzOzAXDNYPUrx6wxOT9QjkwL4DnWMvODV5wUAP4EclxbiM+i88meUJMUYA3pSMu987qoRLqwDW+10j0rr/4QV/lrNwxwGClpSD9enPHJXTdD5i4vY+YK2F2BjzElrYdwDN05x/KpelMOGJGB0AIQGboYxvz23hR+apyVcO+jq2HCklll7wcT31rbMbgrBU93FUtcBfbSdZdlOztILlbpWq90jOqR8Au8VfIQFLZecAAAAASUVORK5CYII=";
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app='test' ng-controller='Test'>
<img src={{base64}} />
</div>

Related

how to deal with ng-src with invalid url in ng-repeat

I would like to show the picture of a user if there is a user in my object list (profileList), and default/error as defaultProfile.png when no user is found ({{item.userProfile}} is null)
I have searched for similar approaches such as
angularjs: ng-src equivalent for background-image:url(…)
and
empty ng-src doesn't update image
My approach to this problem is:
<div ng-repeat="item in profileList">
<div>
<img src='assets/img/defaultProfile.png' data-ng-src="http://example.com/{{item.userProfile}}.jpg" onerror="this.src='assets/img/defaultProfile.png'" />
</div>
<div>
I am able to show error photo however I am still getting error 500,
GET http://example.com/.jpg 500 (INTERNAL SERVER ERROR)
How to avoid getting http://example.com//.jpg?
Thanks a lot
Your current issue is ng-src is still compiled and evaluated to an invalid url when userProfile is undefined.
A simple solution is to use ternary and check for userProfile before deciding with url should be rendered:
<img ng-src="{{ item.userProfile ? 'http://example.com/' + item.userProfile + '.jpg'}} : 'assets/img/defaultProfile.png'" />
It will guarantee that you will always fetch the default image unless item.userProfile is available.
One approach is to use ng-if and ng-hide:
<div ng-repeat="item in profileList">
<div>
<img ng-if="item.userProfile"
data-ng-src="http://example.com/{{item.userProfile}}.jpg" />
<img ng-hide="item.userProfile"
src="assets/img/defaultProfile.png" />
</div>
<div>
When item.userProfile exists, show the ng-src and hide the default otherwise vice versa.
It works.
ng-show
will run no matter {{item.userProfile}} is null or not.
By changing it to
ng-if
Below code is working:
<div ng-repeat="item in profileList">
<div>
<img ng-if="item.userProfile"
data-ng-src="http://example.com/{{item.userProfile}}.jpg" />
<img ng-if="item.userProfile == null"
src="assets/img/defaultProfile.png" />
</div>
note that my profileList is:
$scope.profileList = {userProfile = null}
Thanks a lot

angular - create a new line on HTML

I have a simple question (I hope this). I have a service that return a string as result. The format is something like this:
"
Test1: the association has been accepted.\nTest2: the association has been accepted.\n"
"
On the client side (I'm using Angular 1.5.x) I put that string into a object (say the variable $scope.alert.message). After that I want to print that string in a modal. My html is:
<script type="text/ng-template" id="infoTemplate.html">
<div class="modal-header left" ng-class="['div-' + alert.type, closeable ? 'alert-dismissible' : null]">
<h3 class="modal-title" id="modal-title">Info</h3>
</div>
<div class="modal-body" id="modal-body">
<img class="imm-info" ng-class="['imm-' + alert.type, closeable ? 'alert-dismissible' : null]" />
<p class="col-sm-10 col-sm-offset-2">{{alert.message}}</p><button class="col-sm-3 col-sm-offset-5 btn " ng-class="['button-' + alert.type, closeable ? 'alert-dismissible' : null]" ng-click="cancel()">OK</button>
</div>
</script>
You can see the '{{alert.message}}'. My problem is that my message "doesn't display" the character '\n'. So it doesn't create more than one line. An example here:
example
I use the white-space: pre-wrap CSS style, e.g. :
<p style="white-space: pre-wrap">{{alert.message}}</p>
Try this in HTML:
<pre>{{ alert.message }}</pre>
Already answered here:
The < pre > wrapper will print text with \n as text
\n is not interpreted in html. You need to replace these instances with <br/> elements. You could for example replace them with a regex if you do not want to change the original string.
You can write a function where you take the alert-message and split it by "\n"
than iterate trough it via *ngFor.
For example:
<p *ngFor="let msg of getMessageSplitted(alert.message)">{{msg}}</p>

Match Error with Meteor.callLoginMethod

I'm trying to send my login with :
'submit form': function(event) {
event.preventDefault();
event.stopPropagation();
var loginRequest = {
username: event.target.loginUsername.value.toLowerCase(),
password: event.target.loginPassword.value,
};
var callback = function(response) {
Session.set('showLoading', false);
};
Session.set('showLoading', true);
Accounts.callLoginMethod({
methodArguments: [loginRequest],
userCallback: callback,
});
},
But I get an error and I can't figure out what is the thing that create this error :
Exception while invoking method 'login' Error: Match error: Unknown key in field username
...
Sanitized and reported to the client as: Match failed [400]
I founded some informations in the web but nothing that really helped me. I think it's generated when I call Accounts.callLoginMethod
My form looks like this:
<form>
<div class="row">
<div class="input-field col-xs-12 col-sm-8 col-md-6 col-sm-offset-2 col-md-offset-3">
<label for="loginUsername">Username</label>
<input id="loginUsername" type="text" class="form-control" disabled="{{showLoading}}" required>
<br>
<label for="loginPassword">Password</label>
<input id="loginPassword" type="password" class="form-control" disabled="{{showLoading}}" required>
</div>
</div>
<br>
{{#if showLoading}}
{{> loading}}
{{else}}
<div class="text-center">
<button type="submit" class="btn btn-primary">Login</button>
</div>
{{/if}}
</form>
Someone could help me or know what is creating this error ?
Here is my 2 cents. Accounts.callLoginMethod is technically not a documented API function and in theory could change in any future Meteor release. Since it's not documented, the errors that it returns are not well defined and could be confusing.
Since you are just doing password authentication, I would recommend you use Meteor.loginWithPassword(user, password, [callback]) instead. At least this way you have a set of API documentation to fallback on if you get errors such as this (it also returns more specific errors when something goes wrong).
Try switching​ and see if you still receive an error output. If so the error will be one of the below error messages and you can better debug to see what's going on.
“Unrecognized options for login request [400]” if user or password is undefined.
“Match failed [400]” if user isn’t an Object or String, or password isn’t a String.
“User not found [403]” if the email or username provided in user doesn’t belong to a registered user.
“Incorrect password [403]” if the password provided is incorrect.
“User has no password set [403]” if user doesn’t have a password.
If you encounter one of the above errors, then do console.log(username) and make sure it is a string or object with the value that you are expecting.

Knockout Clone Whole Item In foreach

I am trying to clone elements when clicking a button. I was trying to use ko.toJS. On page load it works fine, but when I want clone the items, it is unable to bind the items (like, value, Text, etc.).
Here is the HTML:
<div class="stockItems-inner" data-bind="foreach: StockItems">
<div data-bind="if: Type=='Input'">
<div class="stock_container_input">
<input type="text" data-bind="value: Value" />
</div>
</div>
<div data-bind="if: Type=='Radio'">
<div class="stock_container_control">
<div data-bind="foreach: Options">
<div class="stockLbl">
<input type="radio" data-bind="text: Text, checked:$parent.Value, attr:{'id':Id, 'name': $parent.Text, 'value': Value}" />
<label data-bind="attr:{'for':Id}, text: Text"></label>
</div>
</div>
</div>
</div>
</div>
<div class="addItem">
<button type="button" data-bind="click: CloneItem"><img src="images/add.png" alt="" /></button>
</div>
The View Model:
ConfigurationStockViewModel = function() {
var self = this;
this.StockItems = ko.observableArray();
this.ApplyData = function(data){
self.StockItems(data.Items);
}
this.CloneItem = function(StockItems){
self.StockItems.push(ko.toJS(StockItems));
};
};
When clicking the button, an error is thrown: Unable to process binding. I am using JSON data for binding.
Not exactly sure what end result you want without working code, but sounds like you want to clone the last item in array and add to array?
If so, I think you have an error - your add button click binding will never pass anything to the function you defined, since it is outside the foreach. You need something like this:
this.CloneItem = function() {
var toClone = self.StockItems()[self.StockItems().length - 1]
self.StockItems.push(toClone);
};
Here is a simplified example without radio buttons, etc:
http://jsfiddle.net/5J47L/

Unable to resolve constructor for: ' dojox.mobile.RoundRectCategory'

I use Worklight 5.06 and Dojo 1.8.
After an Eclipse crash it shows this errors on browser's console:
Unable to resolve constructor for: 'dojox.mobile.RoundRectCategory'
Left list not found
this.leftList is indefined
As you can see in this screenshot:
dojo.connect(window, "onload", function() {
dojo.require("dijit.form.NumberSpinner");
});
function dojoInit() {
require(["dojo", "dojo/request/script", "dojo/parser", "dojox/mobile", "dojox/mobile/compat", "dojox/mobile/deviceTheme",
"dojox/mobile/ScrollableView",
"dojox/mobile/ScreenSizeAware",
"dojox/mobile/FixedSplitter",
"dojox/mobile/Container",
"dojox/mobile/EdgeToEdgeList",
"dojox/mobile/RoundRect", n ",
"
dojox / mobile / Button ",
"
dojox / mobile / GridLayout ",
"
dojox / mobile / Pane ",
"
dojox / mobile / ScrollablePane ",
"
dijit / form / DataList ",
],);
#import url("http://ajax.googleapis.com/ajax/libs/dojo/1.8/dojo/resources/dojo.css");
#import url("http://ajax.googleapis.com/ajax/libs/dojo/1.8/dijit/themes/claro/claro.css");
<script type='text/javascript' src='//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js' data-dojo-config="parseOnLoad:true, async:'legacyAsync'"></script>
<div id="xx" data-dojo-type="dojox.mobile.ScrollableView">
<h2 data-dojo-type="dojox.mobile.RoundRectCategory" style="text-align: center;">Filtro</h2>
<div data-dojo-type="dojox.mobile.RoundRect">
<div data-dojo-type="dojox.mobile.Pane" style="text-align: center;">
<input id="lll" type="text" onblur="ordinaItemCataloghi('cc')">
<input id="ddd" type="text" placeholder="Descrizione catalogo" onblur="ordinaItemCataloghi('dd')>
<input id=" linea_prodotto " type="text " placeholder="Linea prodotto "
onblur="ordinaItemCataloghi( 'll') ">
</div>
</div>
<h2 data-dojo-type=" dojox.mobile.RoundRectCategory "
style="text-align: center; ">Elenco
cataloghi
</h2>
<ul id="ulElencoCataloghi "></ul>
</div>
everything worked up before the crash of eclipse. What could have happened?
Clean your proyect on Eclipse
edit this row
<input id="ddd" type="text"placeholder="Descrizione catalogo" onblur="ordinaItemCataloghi('dd')**"**>
and
<h2 data-dojo-type="dojox.mobile.RoundRectCategory" style="text-align: center;">Elenco cataloghi</h2>
require only:
"dojox/mobile/RoundRect",
Few things I notice:
In your require() you have some weird thing after dojox/mobile/RoundRect. That `n", doesn't belong there I suppose?
You didn't add a module called dojox/mobile/RoundRectCategory in your require()
Can you also post the callback of the require()? It's probably a mismatch between the name of the module and the position of the parameter in the callback. Without callback it's hard to find out (or to eliminate this possibility).
I got similar error with a Dojox DataGrid and migrating from 1.8 to 1.10. in my case it turned out the dot notation required to be changed to slash notation:
<!-- Change syntax from: -->
<table id="resultsUsers" data-dojo-type="dojox.grid.DataGrid">
<!-- Change syntax to: -->
<table id="resultsUsers" data-dojo-type="dojox/grid/DataGrid">