Need to catch clicked image as base64 in Ionic 4 - ionic-framework

Trying on a web page. I am using PWA, Ionic 4 and Android.
In my home.html I have added a button
<!-- Trigger the file input -->
<ion-button expand="full" (click)="captureImage()">
<ion-icon slot="start" name="camera"></ion-icon>
Capture Image
</ion-button>
on my home.ts I have this code below:
captureImage() {
this.fileinput.nativeElement.click();
}
On clicking the button, it open the option to select camera app, now when I select the camera app, it allows me to click image. After clicking it takes me back to screen. Here I want to fetch the image as base64.
How do I do that?

You can get the files from :
this.fileinput.nativeElement.files;
For converting the files after selection, use FileReader.readAsDataUrl().
You can find the full code for the same here:
https://forum.ionicframework.com/t/ionic-4-pwa-camera/151148/12
To store file:
Call this before uploading:
upload()
{
const fileList: FileList = this. fileinput.nativeElement.files;
if (fileList && fileList.length > 0)
{
this.firstFileToBase64(fileList[0]).then((result: string) =>
{
this.base64File = result;
}, (err: any) => {
// Ignore error, do nothing
this.base64File = null;
});
}
}
private firstFileToBase64(fileImage: File): Promise<{}> {
return new Promise((resolve, reject) => {
let fileReader: FileReader = new FileReader();
if (fileReader && fileImage != null) {
fileReader.readAsDataURL(fileImage);
fileReader.onload = () => {
resolve(fileReader.result);
};
fileReader.onerror = (error) => {
reject(error);
};
} else {
reject(new Error('No file found'));
}
});
}

Related

Search bar (ionInput) event to filter output

I am using search bar ionInput event to search among the list but filtered output is shown for one list and not shown for other list on other page?
my first list code :-
HTML
<ion-searchbar class="ion-no-padding" showcancelbutton="true" (ionInput)="onSearchChange($event)" placeholder="search manga"></ion-searchbar>
<ion-list no-lines *ngFor="let anime of animelist" >
<ion-item>
<h2>Name : {{anime.t}}</h2>
</ion-item>
</ion-list>
My .ts file
getanimelist(){
this.restProvider.getanimelist().subscribe(data => {
this.animelist = data;
console.log('result ' + JSON.stringify(data) );
});
this.items= this.animelist;
}
onSearchChange(evt: any) {
this.getanimelist();
console.log(this.items);
console.log(evt);
const val = evt.srcElement.value;
console.log(val);
if (!val){
return ;
}
this.animelist = this.items.filter((data) => {
// console.log(data);
if (data.t && val){
if (data.t.toLowerCase().indexOf(val.toLowerCase()) > -1){
return true;
}
return false;
}
})
}
my api call for this:-
apiUrl= 'https://www.mangaeden.com/api';
getanimelist(){
return this.http.get(this.apiUrl+'/list/0').pipe(
map(result => {
return result['manga'];
})
)}
}
the output for this list does get filter and my list do get updated on the page as per the value enterd but for my second list on other page iam using the same concept same code but my output is not getting filtered on the page, inside the console log i see the filtered result but my page list is not getting updated
second list code below :-
HTML
<ion-searchbar class="ion-no-padding" showcancelbutton="true" (ionInput)="onSearchChange($event)" placeholder="search manga"></ion-searchbar>
<ion-list no-lines *ngFor="let anime of animelist" >
<ion-item >
<h2>Name : {{anime.t}}</h2>
</ion-item>
</ion-list>
My .ts file
getanimelist(){
//this.isLoaded = true;
this.restProvider.getpageanimelist().subscribe(data => {
this.animelist = data;
//console.log('result ' + JSON.stringify(data) );
});
this.items= this.animelist;
}
onSearchChange(evt: any) {
this.getanimelist();
const val = evt.srcElement.value;
console.log(this.items);
console.log(evt);
console.log(val);
if (!val){
return ;
}
this.animelist = this.items.filter((data) => {
// console.log(data);
if (data.t && val){
if (data.t.toLowerCase().indexOf(val.toLowerCase()) > -1){
return true;
}
return false;
}
});
}
my api call for the 2nd list:-
getpageanimelist(){
return this.http.get(this.apiUrl+'/list/0/?p=0&l=26').pipe(
map(result => {
return result['manga'];
})
)}
hope someone can help why is the filtered result not shown for my 2nd list ?
I stored the filter data in a new array rather than in animelist array (which is getting data from the api in the subscribe block) which was causing the whole array to call again and hence no filtered data can be viewed
my changed code in .ts
onSearchChange(evt: any) {
this.getanimelist();
const val = evt.srcElement.value;
if (!val){
return ;
}
this.newarray = this.items.filter((data) => { //stored data in new array
if (data.t && val){
if (data.t.toLowerCase().indexOf(val.toLowerCase()) > -1){
return true;
}
return false;
}
})
}
and hence i call the new array in my html and now when i type the name of the anime the list get filtered accordingly without any issue.
Changed Html
<ion-searchbar class="ion-no-padding" showcancelbutton="true" (ionInput)="onSearchChange($event)" placeholder="search manga"></ion-searchbar>
<ion-list no-lines *ngFor="let anime of newarray" >
<ion-item >
<h2>Name : {{anime.t}}</h2>
</ion-item>
</ion-list>

How to filter the data from API json using ionic?

I would like to have a search bar that filters the results I tried to do it but it does not work. When I'm looking for something, nothing happens, no mistake, so I'm wrong, but I do not know what, I'm new to typescript and I ask for help. Thanks in advance
Home.html
---------
<ion-searchbar (ionInput)="filterItems()"
[showCancelButton]="shouldShowCancel" (ionCancel)="onCancel($event)"></ion-searchbar>
<ion-list>
<ion-item *ngFor="let item of items" (click)="itemClick(item.id)">
<h1>{{item.id}}</h1>
{{item.title}}
</ion-item>
</ion-list>
Home.ts
-------
export class HomePage {
public items:any;
constructor(public http:HttpClient) {
this.loadData();
}
searchTerm: string ;
loadData() {
let data:Observable<any>;
data = this.http.get('https://jsonplaceholder.typicode.com/photos');
data.subscribe(result => {
this.items = result;
this.filterItems= this.items;
})
}
filterItems(ev:any){
this.loadData();
const val = ev.target.value;
this.filterItems = this.items.filter(item =>
{
item.titre.toLowerCase().indexOf(this.searchTerm.toLowerCase()) > -1;
})
}
itemClick(itemid:number){
alert(itemid);
}
}
so you can do this in your html
<ion-searchbar [formControl]="searchTerm"></ion-searchbar>
Then in your .ts file declare before the constructor
public searchTerm: FormControl;
Then inside your ngOnInit, have this function that listens to user input and waits a while before filtering
this.searchTerm.valueChanges
.pipe(debounceTime(700))
.subscribe(search => {
this.items = this.filterItems(search);
});
Then your final method for the filter
filterItems(search) {
this.items = this.filterItems;
return this.items.filter(item => {
return item.titre.toLowerCase().indexOf(search.toLowerCase()) > -1
});
}
I hope this helps

How to use ImagePicker to select image and display in Ionic Native

I'm developing an Ionic app, and one task is to select a profile via camera or gallery, and I use Ionic Native ImagePicker to select picture and crop, it can select and crop, but not display in front html page, my code is as below:
openImagePickerCrop(){
this.imagePicker.hasReadPermission().then(
(result) => {
if(result == false){
// no callbacks required as this opens a popup which returns async
this.imagePicker.requestReadPermission();
}
else if(result == true){
this.imagePicker.getPictures({
maximumImagesCount: 3
}).then(
(results) => {
for (var i = 0; i < results.length; i++) {
this.crop.crop(results[i], {quality: 100}).then(
newImage => {
this.imgResponse.push('data:image/jpeg;base64,' + newImage);
console.log("Image selected - " + newImage);
},
error => console.error("Error cropping image", error)
);
}
}, (err) => console.log(err)
);
}
}, (err) => {
console.log(err);
});
}
And this is my html code:
<ion-item class="input-item">
<ion-label position="floating">Photo</ion-label>
<div class='images' *ngFor="let img of imgResponse">
<img src="{{img}}" alt="" srcset="" />
</div>
<ion-card-content>
<ion-button color="medium" size="large" (click)="openImagePickerCrop()">
<ion-icon slot="icon-only" name="camera"></ion-icon>
</ion-button>
</ion-card-content>
</ion-item>
Where am I doing wrong, pls help.
Update:
To check if it's due to the crop function, I have updated functions as below:
openImagePicker(){
this.imagePicker.hasReadPermission().then(
(result) => {
if(result == false){
// no callbacks required as this opens a popup which returns async
this.imagePicker.requestReadPermission();
}
else if(result == true){
this.imagePicker.getPictures({
maximumImagesCount: 1
}).then(
(results) => {
for (var i = 0; i < results.length; i++) {
this.imgResponse.push('data:image/jpeg;base64,' + results[i]);
console.log("Image selected - " + results[i]);
}
}, (err) => console.log(err)
);
}
}, (err) => {
console.log(err);
});
}
But still not working, and the console doesn't capture anything.

html2canvas - the screenshotted canvas is always empty/blank

I have a div that i want to screenshot and save,
here is my code
function _download(uri, filename)
{
var el = $('.sf-download-button');
if (el.length)
{
var link = document.createElement('a');
if (typeof link.download === 'string')
{
link.href = uri;
link.download = filename;
document.body.appendChild(link);
//simulate click // this causes page to download an empty html file not sure why
link.click();
//remove the link when done
document.body.removeChild(link);
}
else
{
window.open(uri);
}
}
}
function _save()
{
window.takeScreenShot = function ()
{
var a =document.getElementById("my-div");
html2canvas(document.getElementById("the-div-that-i-want-to-screenshot"), {
onrendered: function (canvas)
{
document.body.appendChild(canvas);
a.append(canvas);
},
width: 220,
height: 310
});
};
$("#btnSave2").click(function ()
{
html2canvas(document.getElementById("data"), {
onrendered: function (canvas)
{
_download_card(canvas.toDataURL(), 'save.png');
}
});
});
}
This is the code i got it from web and added some of my own stuff.code was working i believe but right now, when I click on the button show me the image, it creates the image i can see it but it is just blank.
I tried every possible code combination from jsfiddle and all that and couldn't get anything different as a result.
What could be going wrong here?
I solved the problem by simply changing the browser,
It was not working with Chrome but works perfectly on Mozilla.
Also i changed the code to this,
$("#btnSave").click(function() {
html2canvas($("#card"), {
onrendered: function(canvas) {
theCanvas = canvas;
document.body.appendChild(canvas);
// Convert and download as image
$("#img-out").append(canvas);
// Clean up
//document.body.removeChild(canvas);
}
});
});
Works perfect on Mozilla only.

Use getUserMedia with ionic get only black screen

Im testing some media features with ionic and im stuck while trying to set the camera output into a video tag using getUserMedia using this code:
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia({ audio: false, video: { width: 500, height: 500 } },
function(stream) {
console.log("Im streaming!!", stream);
var video = document.querySelector('video');
console.log("video element", video);
video.src = window.URL.createObjectURL(stream);
video.onloadedmetadata = function(e) {
console.log("stream start");
video.play();
};
},
function(err) {
console.log("The following error occurred: " + err.name);
}
);
} else {
console.log("getUserMedia not supported");
}
this is the html:
<ion-pane>
<ion-header-bar class="bar-stable">
<h1 class="title">Ionic Blank Starter</h1>
</ion-header-bar>
<ion-content>
<video id="video" autoplay="autoplay" width="500" height="500"></video>
</ion-content>
</ion-pane>
i can actually get only a black screen. Is my approach right or im missing something?
I managed to reproduce the problem and solved it by using the constraints options. Using constraints you can set the sourceId that allows you to select between front or rear camera. Im sure that your device has no front camera and i guess this is why you are getting the black screen.
First we create our constraint options:
var constraints = {};
MediaStreamTrack.getSources (function(sources) {
sources.forEach(function(info) {
if (info.facing == "environment") {
constraints = {
video: {
optional: [{sourceId: info.id}]
}
};
}
})
})
Then we call the navigator.getUserMedia:
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia(constraints,
function(stream) {
console.log("Im streaming!!", stream);
var video = document.querySelector('video');
console.log("video element", video);
video.src = window.URL.createObjectURL(stream);
video.onloadedmetadata = function(e) {
console.log("stream start");
video.play();
};
},
function(err) {
console.log("The following error occurred: " + err.name);
}
);
} else {
console.log("getUserMedia not supported");
}
Warning: MediaStreamTrack.getSources returns a promise so that means that if you try to run your navigator.getUserMedia code at once, it will fail. You will have to wrap it in a function and run it as a callback.
More info about camera and audio source selection can be found here:
https://developers.google.com/web/updates/2015/10/media-devices
also a nice example here:
https://simpl.info/getusermedia/sources/
The final solution to this problem is that getUserMedia require a runtime permission check to work. To achieve that i used this plugin. Then this worked like a charm:
cordova.plugins.diagnostic.requestRuntimePermission(function(status){
if(cordova.plugins.diagnostic.runtimePermissionStatus.GRANTED){
navigator.getUserMedia({video: true, audio: false}, function(localMediaStream) {
var video = document.querySelector('video');
video.src = window.URL.createObjectURL(localMediaStream);
video.onloadedmetadata = function(e) {
console.log('Stream is on!!', e);
};
}, errorCallback);
}
});