When iterating through an array of items for ngFor, the (click) event is failing to attach to each list item, for some reason it just doesn't attach and when I click on each of the list items, the function is not triggered.
Here is the HTML for the list:
<ion-list class="queue-page--actions__haircut__tab-open" radio-group *ngIf="haircutTab" [(ngModel)]="selectedCut">
<ion-list-header class="queue-page--actions__haircut__tab__header">
Select a cut
</ion-list-header>
<ion-item *ngFor="let item of getCuts()" (click)="open($event, item)">
<ion-label>{{item.name}}</ion-label>
<ion-label>£{{item.price}}</ion-label>
<ion-radio checked="{{item.name == selectedCut}}" value="{{item.name}}"></ion-radio>
</ion-item>
</ion-list>
Get cuts is the function on the controller for the page (this.cuts is of type array and returns an array of json objects):
public getCuts(){
return this.cuts;
}
And finally, the open() function is as follows:
public open(event, item){
alert("Clicked");
console.log(item)
}
Can't figure out what's going wrong here, perhaps a suspicion of scope issues but really not sure.
Try like this
<ion-item *ngFor="let item of cuts" (click)="open(item)">
:
</ion-item>
Thanks to this post on the Ionic 2 forum I have found a solution to the problem presented here.
Instead of using (click), I am now using (ionSelect) on the ion-radio element. An example can be seen here:
<ion-item *ngFor="let item of cuts" (click)="open(item)">
<ion-label>{{item.name}}</ion-label>
<ion-label>£{{item.price}}</ion-label>
<ion-radio (ionSelect)="cutChanged(item.name)" checked="{{item.name == selectedCut}}" value="{{item.name}}"></ion-radio>
</ion-item>
Where the function on the controller for cutChanged() is like so:
cutChanged(cut){
alert(cut);
}
This implementation now works and fires on click events. Perhaps something unusual with how radio buttons work in Ionic?
Your getCuts() method is not required.
No need to pass the event when the open() function is called. Also there is a semicolon missing in your open() method. Final Code :
<ion-list class="queue-page--actions__haircut__tab-open" radio-group *ngIf="haircutTab" [(ngModel)]="selectedCut">
<ion-list-header class="queue-page--actions__haircut__tab__header">
Select a cut
</ion-list-header>
<ion-item *ngFor="let item of cuts" (click)="open(item)">
<ion-label>{{item.name}}</ion-label>
<ion-label>£{{item.price}}</ion-label>
<ion-radio checked="{{item.name == selectedCut}}" value="{{item.name}}"></ion-radio>
</ion-item>
</ion-list>
open() function will be :
public open(event, item){
alert("Clicked");
console.log(item);
}
Related
I have two components to show data. The table view and the graph view. Both components has the same data. I use a toggle switch button to switch between these views. This is my code:
<ion-header>
<ion-toolbar class="toolbar-color">
<ion-title>Views</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-grid>
<ion-row>
<ion-col>
<div class="ion-text-start">
<ion-item>
<ion-label>Switch to table view</ion-label>
<ion-toggle (click)="showTable()"></ion-toggle>
</ion-item>
</div>
</ion-col
</ion-row>
<ion-row>
<ion-col>
<app-tableview hidden="true" id="tableview"></app-tableview>
<canvas height="200" #lineCanvas></canvas>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
The default view is the graphview via chart.js. Both components works fine. This is my code to hide and show:
showTable() {
if (this.tableHidden === true) {
this.tableHidden = false;
document.getElementById("tableview").hidden = false;
} else if (this.tableHidden === false) {
this.tableHidden = true;
document.getElementById("tableview").hidden = false;
}
}
When I click on the toggle switch it doesn't hide the graphview but it shows the table view among each other. I have tried the visibility from this post but doesn't work.
JavaScript hide/show element
How can I switch between the components and show only view?
JSFiddle link: https://jsfiddle.net/f8a3wgxb/
An example based off #alex87's comment:
<ng-container *ngIf="!tableHidden">
<app-tableview id="tableview"></app-tableview>
</ng-container>
<ng-container *ngIf="tableHidden">
<canvas height="200" #lineCanvas></canvas>
</ng-container>
Doesn't have to be an ng-container, but that Angular-only tag will not add anything to the DOM. You can always use a or anything else to do just the same...
You can also neaten it up by using an *ngIfElse...
https://angular.io/api/common/NgIf
Note: I tend to go overboard in my tag wrapping, thus the ng-containers, but *ngIf is typically available on almost all tags, as is hidden - per your usage.
Edit: Fixed the hidden variable name - I was lazy and didn't go back up to find what exactly you'd called it.
Edit #2: You can tidy up and minimise your setting of the hidden variable, instead of needing the if/else.
// This toggles between true/false
this.tableHidden = !this.tableHidden;
document.getElementById("tableview").hidden = !this.tableHidden;
Reduced to only two lines.
I have 2 nested ngFor loops.
The first
<ion-item-group *ngFor="let team of shift.teams_assigned">
Defines team and I would like to use team as a selector for a child loop like this
<ion-item *ngFor="let member of shift.members_assigned.team">
Is there a specific syntax to access the key of an array like members_assigned.$_variable_key_i_want_to_loop
You should do it like that if I well understand your question because it is not clear to me
<ion-item *ngFor="let team of shift.teams_assigned">
<ion-item *ngFor="let member of team">
</ion-item>
</ion-item>
I am attempting to filter a list of items the code below worded fine in angular js on the web but we can't expect Ionic to work now can we?
<ion-list *ngIf="items.length">
{{items[0].title}}
<ion-item ng-repeat="item in items | filter:searchLog">
{{item == undefined}}
<!--<ion-icon name="clipboard" item-left></ion-icon>
<h2><b>Title: {{item.title}}</b></h2>
<h3><b>Caller: {{item.caller.name}} - {{item.caller.number}}</b></h3>
<h3><b>Location: {{item.caller.location}}</b></h3>
<h3><i>Dispatcher: </i>{{item.dispatcher.name}} at {{item.timeStamp}}</h3>
<h3><b>Dropped: {{item.canceled}}</b></h3>
<h3 style="white-space: normal;"><i>Details:</i> {{item.details}}</h3>-->
</ion-item>
</ion-list>
This is what my screen shows:
car out of gas
true
For the life of me I cannot understand this because if I print {{ items[0].title }} it works fine in the repeat list meaning that it is not giving me this item object back from the ng-repeat call. What is even weirder is that *ngFor works but I cannot filter it :-( Please help
TL;DR: ng-repeat in angular is returning one undefined object.
Use *ngFor with pipe (i.e. filter). If it is still not working then there is some problem with your pipe (filter). Code should look like below:
<ion-list *ngIf="items.length">
{{items[0].title}}
<ion-item *ngFor="let item of items | searchLog">
<ion-icon name="clipboard" item-left></ion-icon>
<h2><b>Title: {{item.title}}</b></h2>
<h3><b>Caller: {{item.caller.name}} - {{item.caller.number}}</b></h3>
<h3><b>Location: {{item.caller.location}}</b></h3>
<h3><i>Dispatcher: </i>{{item.dispatcher.name}} at {{item.timeStamp}}</h3>
<h3><b>Dropped: {{item.canceled}}</b></h3>
<h3 style="white-space: normal;"><i>Details:</i> {{item.details}}</h3>
</ion-item>
</ion-list>
I am trying to use ngIf within an ngFor but it's just breaking my code. Below is my code:
<ion-row *ngIf="{{i % 3}}===0" *ngFor="let category of categories; let i=index">
I need to check if the index mod 3 is equal to zero
You can overwrite your code like:
<ion-row *ngFor="let category of categories; let i=index">
<ng-container *ngIf="{{i % 3}}===0">
...
</ng-container>
</ion-row>
ng-container behaves the same as template but you can use common syntax like *ngIf and *ngFor
you can't put ngIf on the same component as ngFor
Angular disallows such construction
Using i before initializing it in ngFor will never work
If you *ngIf gets a false value the *ngFor would never be created in the first place - see point 1:-)
I'm building an ionic app. I have a state where the user can see all of their posts. Each post has many fields, one of which is 'active' - boolean field.
I'm rendering the list by:
<ion-item ng-repeat="post in posts | filter:{active:true}" ng-click="goToPost(post.id)"
class="item item-thumbnail-left">
<some fields here />
</ion-item>
Then the user has an option to deactivate a post.
<ion-option-button class="button-assertive" ng-click="deactivate(post.id, $index)">
DEACTIVATE
</ion-option-button>
This option makes a request to the backend, and also it locally sets the active field of the post into "false". After the deactivation is complete, I can't get the ng-repeat to re-filter the list - since the current post should no longer appear in the list of active posts.
I tried $scope.$apply() and it threw the $digest error... I tried to add ng-change and ng-model, and that didn't work either. I also tried reloading the state completely, but for some reason, I can't get this done.
Can anyone help me? Thanks in advance!
Look at the fiddle
<div ng-app="app" ng-controller="demoController">
<ion-item ng-repeat="post in data | filter:{activated:true}" ng-click="deativate(post.id)">
{{post.col1}} {{post.activated }} {{"click Me"}} </br>
</ion-item>
</div>
var app= angular.module("app",[]);
app.controller('demoController', ['$scope',
function($scope) {
$scope.data = [
{id:1,col1:"abc",activated:true},
{id:2,col1:"abc1",activated:true},
{id:3,col1:"abc2",activated:true},
{id:4,col1:"abc3",activated:true},
{id:5,col1:"abc4",activated:false},
{id:6,col1:"abc5",activated:true},
];
$scope.deativate = function(id){
angular.forEach($scope.data,function(item){
if(item.id === id){
item.activated = false;
}
})
}
}]);
and for your code you can share your code snippet.