Search bar (ionInput) event to filter output - ionic-framework

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>

Related

In angular, when a page is opened in edit mode using query params, value in dropdown is not coming in mat select

customer_name is not displayed in dropdown.
In .ts file, in ngOnInit() I have used query params to open a page in edit mode.
ngOnInit(): void {
this.addInvoiceItem();
this.route.queryParams.subscribe((params) => {
if (params._id === undefined) {
this.isEdit = true;
console.log(this.isEdit);
} else {
this._id = params._id;
this.service.fetchInvoiceById(this._id).subscribe((data) => {
this.invoice = data;
console.log(this.invoice.customer_details);
this.customerService
.fetchCustomerById(this.invoice.customer_details)
.subscribe((data) => {
this.invoice.customer_details = data;
console.log(this.invoice.customer_details);
});
});
}
this.customerService.fetchAllCustomers().subscribe((data) => {
this.custList = data;
console.table(this.custList);
});
this.availService.fetchAllCustomers().subscribe((data) => {
this.servicesList = data;
console.table(this.servicesList);
});
});
}
In console.log(this.invoice.customer_details) I can see customer_name in debug. But in display customer_name is not coming.
In html file,
<mat-select
name="customer_details"
[(ngModel)]="invoice.customer_details"
#customer_details="ngModel"
(selectionChange)="updateAddress()"
required
[displayWith]="displayCustomer"
>
<mat-option
*ngFor="let cust of custList"
[value]="cust"
required
>
{{ cust.customer_name }}
</mat-option>
</mat-select>

Need to catch clicked image as base64 in Ionic 4

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'));
}
});
}

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

infinte scroll with loading msg after 10 items

I am displaying a list of items. I want, when we scroll, after displaying 10 items. it displays " loading more..."
(ionInfinite)="doInfinite($event)"
is not triggering.
.html file
<ion-content padding>
<ion-list>
<ion-item *ngFor="let i of items">{{i}}</ion-item>
</ion-list>
<ion-infinite-scroll (ionInfinite)="doInfinite($event)">
<ion-infinite-scroll-content loadingSpinner="bubbles" loadingText="Loading more data...">
</ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-content>
.ts file
import { IonInfiniteScroll, IonVirtualScroll } from '#ionic/angular';
export class FoodMenuPage implements OnInit {
#ViewChild(IonInfiniteScroll) infiniteScroll: IonInfiniteScroll;
items = [];
constructor() {
for (let i = 0; i < 30; i++) {
this.items.push( this.items.length );
}
}
doInfinite(infiniteScroll) {
console.log('Begin async operation');
setTimeout(() => {
for (let i = 0; i < 30; i++) {
this.items.push( this.items.length );
}
console.log('Async operation has ended');
infiniteScroll.complete();
}, 500);
}
HTML
<ion-infinite-scroll (ionInfinite)="doInfinite($event)">
<ion-infinite-scroll-content loadingSpinner="bubbles" loadingText="Loading more data...">
</ion-infinite-scroll-content>
<div *ngIf="pagingEnabled" class="nomore_data"> No more data is available.</div>
TS
if (this.image1 != 0) {
for (let i in this.image1) {
this.images = this.images.concat(this.image1[i]);
}
} else {
this.pagingEnabled = true;
} \\image1 and image have same json value
if (Infinitescroll) { \\every scroll infinite has been fire
Infinitescroll.target.complete();\\every scroll tarhas been completed
}
no need for viewchild or anything

Filter results with ion-select

I am new to ionic, following some tutorials and trying to learn and apply other stuff. I think what I'm trying to achieve is quite simple, but I can't seem to have it working.
What I'm trying to do is simply to filter results using the ion-select element to display its correspondent pick from the select.
So what I have is this ion-select where I'm using the ngModel and ngFor to filter which options the user should have, and once the user select their option, the app should only display the correspondent results, in this case, a Sport (so if the user picks 'Soccer' in the ion-select, only the 'Soccer' ion-cards should be displayed, I have those connected in the back end.
I'm adding here a piece of the code, but I'm afraid you might need other piece of code to get it more clear, so let me know please. Cheers guys!
<ion-content padding>
<ion-item>
<ion-label>Filter by Sport</ion-label>
<ion-select [(ngModel)]="list" multiple="true">
<ion-option *ngFor="let item of list">{{item.sport}}</ion-option>
</ion-select>
</ion-item>
<ion-card *ngFor="let item of list">
<ion-card-content>
<ion-card-title>{{item.title}}</ion-card-title>
<p>Sport: {{item.sport}}</p>
<p>Participants: {{item.players}}</p>
<p>When: {{item.when}}</p>
<p>{{item.description}}</p>
<p>Location: {{item.location}}</p>
<button ion-button block (click)="joinEvent(item)">Join!</button>
</ion-card-content>
</ion-card>
</ion-content>
Edit: Added .ts code below:
export class JoinEventPage {
filterListBy$
filteredList$
list: IEvent[];
joined = [];
constructor(public navCtrl: NavController,
public navParams: NavParams,
public eventProvider: EventsProvider,
public joinedEventsProvider: JoinedEventsProvider) {
}
ionViewDidEnter(){
// create observable
this.filterListBy$ = Observable.from(this.list)
// pull out just the name of the sport
.map((a: any) => a.sport)
// make sure items are distinct
.distinct()
// return an array
.toArray();
// force the initial filtering of the list
this.changeCategory([])
// this.eventProvider.listEvents().subscribe(res=>{
// this.list = res;
// }, error => {
// console.log("Error: " + error.message);
// });
// this.joinedEventsProvider.getStorage('joined-events').then(res => {
// if(res){
// this.joined = res;
// }
// });
}
ionViewDidLoad() {
console.log('ionViewDidLoad JoinEventPage');
}
joinEvent(item){
for(let event of this.joined){
if(event.id == item.id){
console.log("You already joined this event!")
return;
}
}
this.joined.push(item);
this.joinedEventsProvider.setStorage('joined-events', this.joined);
}
changeCategory(_value) {
// if nothing selected, show all
if (!_value.length) {
return this.filteredList$ = Observable.from(this.list).toArray();
}
// if something selected, filter the list based on the item selected which
// will be in the array parameter "_value"
this.filteredList$ = Observable.from(this.list)
.filter((i) => { return _value.indexOf(i.sport) !== -1 })
.toArray()
}
}
Solution: The only change I did to the .ts file following Aaron's solution is below:
ionViewDidEnter(){
this.eventProvider.listEvents().subscribe(res=>{
this.list = res;
// create observable
this.filterListBy$ = Observable.from(this.list)
// pull out just the name of the sport
.map((a: any) => a.sport)
// make sure items are distinct
.distinct()
// return an array
.toArray();
// force the initial filtering of the list
this.changeCategory([])
this.joinedEventsProvider.getStorage('joined-events').then(res => {
if(res){
this.joined = res;
}
});
});
}
see full answer here, but highlights are below
https://stackblitz.com/edit/ionic-tkqzr6
ngOnInit() {
// create observable
this.filterListBy$ = Observable.from(this.list)
// pull out just the name of the sport
.map((a: any) => a.sport)
// make sure items are distinct
.distinct()
// return an array
.toArray();
// force the initial filtering of the list
this.onChange([])
}
when the user selects an option, we call onChange
onChange(_value) {
// if nothing selected, show all
if (!_value.length) {
return this.filteredList$ = Observable.from(this.list).toArray();
}
// if something selected, filter the list based on the item selected which
// will be in the array parameter "_value"
this.filteredList$ = Observable.from(this.list)
.filter((i) => { return _value.indexOf(i.sport) !== -1 })
.toArray()
}
now in the html
<ion-item>
<ion-label>Filter by Sport</ion-label>
<ion-select multiple="true" (ionChange)="onChange($event)">
<ion-option *ngFor="let item of (filterListBy$ | async)">{{item}}</ion-option>
</ion-select>
</ion-item>