How can i use *ngIf condition in below code? - ionic-framework

Here I want to check the condition but I am not able to check.
<text-avatar id="av" item-start [text]="item.BN" [color]="item.color">
<ion-icon id="check" name="checkmark-circle" float-start></ion-icon>
</text-avatar>

As simple as that, where someBoolean can be any boolean value retrieved through component class
home.tst
. . .
class Home {
var someBoolean: boolean = false;
var myArray: any[];
constructor() {
// compare values with array here or in any other method
if (true) {
someBoolean = true;
}
}
}
home.html
<text-avatar id="av" item-start [text]="item.BN" [color]="item.color" *ngIf="someBoolean">
<ion-icon id="check" name="checkmark-circle" float-start></ion-icon>
</text-avatar>

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

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>

get checkbox values in real time with a reactive form Angular

I have a list of country objects, that I access and use with my reactive form. I create each one as a form control dynamically, because this list will be changing. Then I attempt to get the form and values in real time (not using a submit button), as the checkboxes get clicked, by using the ngOnChanges hook. this is obviously not working, what hook should I use? on another note, is this a bad way to accomplish this? what would be a better approach?
component
export class GeoDropComponent implements OnInit, OnChanges {
countries = [
{
name : 'USA',
continent : 'north america'
},
{
name : 'Canada',
continent: 'north america'
}
];
countriesForm: FormGroup;
constructor() { }
ngOnInit() {
// add checkbox for each country
this.countriesForm = new FormGroup({});
for (let i = 0; i < this.countries.length; i++) {
this.countriesForm.addControl(
this.countries[i].name, new FormControl(false)
)
}
}
ngOnChanges() {
console.log(this.countriesForm);
}
}
html
<div class="geo-list">
<div class="content-box container">
<form [formGroup]="countriesForm">
<div class="country" *ngFor="let country of countries">
<input
type="checkbox"
formControlName="{{country.name}}"
>
{{ country.name }} | {{ country.continent }}
</div>
</form>
</div>
</div>
you can try like this. when ever search checkbox is selected or selected change method will update selected items
pseudo code
<input
type="checkbox"
formControlName="{{country.name}}"
(change)="search(country, $event)
>
component file.
selectedItems : any [] = [];
search(country, event) {
var index = this.selectedItems.indexOf(country.name);
if (event.target.checked) {
if (index === -1) {
this.selectedItems.push(country.name);
}
} else {
if (index !== -1) {
this.selectedItems.splice(index, 1);
}
}
}
}

Dynamically include files (components) and dynamically inject those components

Looking around the next I could not find the answer: How do I dynamicly include a file, based on prop change per say: here some sudo code to intrastate what I'm trying to do!
class Test extends React.Component {
constructor(props){
super(props)
this.state = { componentIncluded: false }
includeFile() {
require(this.props.componetFileDir) // e.g. ./file/dir/comp.js
this.setState({ componentIncluded: true });
}
render() {
return(
<div className="card">
<button onClick={this.includeFile}> Load File </button>
{ this.state.componentIncluded &&
<this.state.customComponent />
}
</div>
)
}
}
so this.props.componetFileDir has access to the file dir, but I need to dynamically include it, and can't really do require() as its seems to running before the action onClick get called. Any help would be great.
Em, Your code looks a bit wrong to me. So I created a separate demo for dynamic inject components.
While in different situation you can use different React lifecycle functions to inject your component. Like componentWillReceiveProps or componentWillUpdate.
componentDidMount() {
// dynamically inject a Button component.
System.import('../../../components/Button')
.then((component) => {
// update the state to render the component.
this.setState({
component: component.default,
});
});
}
render() {
let Button = null;
if (this.state.component !== null) {
Button = this.state.component;
}
return (
<div>
{ this.state.component !== null ? <Button>OK</Button> : false }
</div>
);
}
After you edited your code, it should be something similar to below:
class Test extends React.Component {
constructor(props){
super(props)
this.state = { customComponent: null }
this.includeFile = this.includeFile.bind(this);
}
includeFile() {
System.import(this.props.componetFileDir)
.then((component) => {
this.setState({ customComponent: component.default });
});
}
render() {
return(
<div className="card">
<button onClick={this.includeFile}> Load File </button>
{
this.state.customComponent
}
</div>
)
}
}