Array of methods not working ionic 2 - arrays

I'm working on ionic 2. I've created a menu for my page and an array of contents for menu.
menuItems: Array<{title: string, icon: string, method: any}>
And added elements.
this.menuItems =
[
{title: "Edit Account", icon: "create", method: "editAcount()"},
{title: "Change Password", icon: "create", method: "changePassword()"},
{title: "LogOut", icon: "log-out", method: "logOut()"},
];
And I'm calling methods at run-time.
<ion-item *ngFor = "let item of menuItems" menuClose (click) = "item.method"> <!--like this-->
{{item.title}}
<ion-icon item-end name = "{{item.icon}}"></ion-icon>
</ion-item>
But nothing happens. Methods never get called.
When I do this console.log(item.method) it never shows body, only shows methods names.
same result when I tried interpolation i.e.
<ion-item *ngFor = "let item of menuItems" menuClose (click) = "item.method">
{{item.title}} {{item.method}}<!--methods names only-->
<ion-icon item-end name = "{{item.icon}}"></ion-icon>
</ion-item>
Help me guys.
Here's ts file
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams, ViewController, MenuController } from 'ionic-angular';
import { HomePage } from "../home/home";
import { EditUsersProvider } from "../../providers/edit-users/edit-users";
import { FlashMessageProvider } from "../../providers/flash-message/flash-message";
#IonicPage()
#Component(
{
selector: 'page-user-account',
templateUrl: 'user-account.html',
})
export class UserAccountPage
{
userContents;
menuItems: Array<{title: string, icon: string, method: any}>;
constructor(
public navCtrl: NavController,
public navParams: NavParams,
public viewCtrl: ViewController,
private editUser: EditUsersProvider,
private flashMsg: FlashMessageProvider,
public menuCtrl: MenuController)
{
menuCtrl.enable(true, "menu");
this.userContents = this.navParams.data;
this.menuItems =
[ //Problem might be here.
{title: "Edit Account", icon: "create", method: "editAcount()"},
{title: "Change Password", icon: "create", method: "changePassword()"},
{title: "LogOut", icon: "log-out", method: "logOut()"},
];
}
editAcount()
{
console.log("It never triggers");
}
changePassword()
{
console.log("It never triggers");
}
logOut()
{
console.log("It never triggers");
}
}
Here's template file
<ion-menu #menu id = "menu" [content] = "content">
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item *ngFor = "let item of menuItems" menuClose (click) = "item.method"> <!--this never executes -->
{{item.title}}
<ion-icon item-end name = "{{item.icon}}"></ion-icon>
</ion-item>
</ion-list>
</ion-content>
</ion-menu>

You are setting method property as a string representation of a method call.
It doesn't actually call the method because it is a string literal. The function object (eg: this.editAccount) can be set using arrow function (eg: ()=>this.editAccount())or by using bind() e.g: this.editAccount.bind(this);
Try setting like this:
this.menuItems =
[ //Problem might be here.
{title: "Edit Account", icon: "create", method: () => this.editAcount()},
{title: "Change Password", icon: "create", method: () => this.changePassword()},
{title: "LogOut", icon: "log-out", method: () => this.logOut()},
];
In your template call as:
<ion-item *ngFor = "let item of menuItems" menuClose (click) = "item.method()"> <!--this will execute -->

Related

Array of buttons, some with dropdown, but the dropdown opens on all buttons

I have an array of buttons in an Angular application where I need to display them in a top bar with *ngFor. But only four of them have a dropdown, but when I click on one of those that has a dropdown, the same submenu appears under all the buttons. I believe it could be something very simple that I haven't seen in a general context of Array logic, but I've already tried to pass the loop just inside the button itself, but in this case, each dropdown appears completely shifted to the left of the entire group of buttons. Does anyone have an idea how to solve this?
Here's code:
Component.html
<div *ngFor="let item of menuButtons" class="d-inline-block">
<div class="btn-group">
<button [ngStyle]="!showLabel && { 'color': '#495057' }" type="button" class="btn" (click)="catch(item.icon)">
<i class="material-icons-outlined">{{item.icon}}</i>
<span>{{item.label | translate}}</span>
</button>
<div [ngClass]="Class" (mouseleave)="closeLabel()" class="dropdown-menu">
<kt-info-label ngbDropdownItem *ngIf="chosenLabel === 'info'"></kt-info-label>
<kt-mass-actions-label ngbDropdownItem *ngIf="chosenLabel === 'rocket_launch'"></kt-mass-actions-label>
<kt-layout-label ngbDropdownItem *ngIf="chosenLabel === 'edit'"></kt-layout-label>
<kt-save-label ngbDropdownItem *ngIf="chosenLabel === 'save'"></kt-save-label>
</div>
</div>
/* Array com ícones, textos Label */
public menuButtons: Array<any> = [
{icon: 'arrow_back', label: 'MUB.T115'},
{icon: 'info', label: 'MUB.T658'},
{icon: 'file_download', label: 'MUB.T593'},
{icon: 'rocket_launch', label: 'MUB.T2114'},
{icon: 'dashboard_customize', label: 'MUB.T2154'},
{icon: 'edit', label: 'MUB.T173'},
{icon: 'add_circle_outline', label: 'MUB.T2210'},
{icon: 'delete', label: 'MUB.T80'},
{icon: 'save', label: 'MUB.T62'}
]
showLabel: boolean = false
public chosenLabel: string = ""
public Class: string= 'open-'
catch(icon: string) {
if (this.chosenLabel != icon || this.showLabel) {
this.closeLabel()
}
if(!this.showLabel) {
this.chosenLabel = icon
this.Class = `${this.Class}${icon}`
this.showLabel = true
} else {
this.closeLabel()
}
if (this.chosenLabel === 'arrow_back') {
this.back()
}
}
closeLabel() {
this.showLabel = false
this.Class = 'open-'
}
back(): void {
this.location.back()
}

when i push select2OptionData object in an array, select2 don't display any value

select2 in my angular project. I want to display a select of an array of certificate requested from an api. For each element if I create and push a select2OptionData Object in an array, but when i want to display it in the Html page it is selected but without any option. When i create an array of object like the gitHub demo everything's right.
Can you help me please.
Here is the ts
export class DashboardCvComponent implements OnInit, OnDestroy {
certificateForm: FormGroup;
certificates: Array<Certificate>;
certificatesTypes: Array<Select2OptionData>;
exampleData: Array<Select2OptionData>;
constructor(private formBuilder: FormBuilder, private certificatesService: CertificatesService,
private trainingsService: TrainingsService, private authService: AuthenticationService,
private datepipe: DateFormatPipe, private CvService: CVService, private fileUploaService: FileUploadService) {
this.certificatesTypes = [];
this.exampleData = [];
}
ngOnInit() {
// get certificate types
this.certificatesService.getAllCertificatesType('50').subscribe(
(response) => {
// console.log('-> CERTIFICATES TYPES LOADING successful : ', response);
/* this.certificatesTypes = response.data; */
response.data.forEach(element => {
const certif = {id: element.id.toString(), text: element.name};
this.certificatesTypes.push(certif);
});
this.exampleData = [{
id: 'basic1',
text: 'Basic 1'
},
{
id: 'basic2',
disabled: true,
text: 'Basic 2'
},
{
id: 'basic3',
text: 'Basic 3'
},
{
id: 'basic4',
text: 'Basic 4'
}]
console.log('les certif', this.exampleData, this.certificatesTypes);
},
(error) => {
console.log('-> CERTIFICATES TYPES LOADING failed : ', error);
},
() => {
}
);
and the html
<div class="dashboard--degrees">
<app-certificate *ngFor="let certificate of certificates" [certificate]=certificate [url]=url></app-certificate>
<button class="button button--bluegreen" type="button" data-modal="modal-certificate">
<svg class="icon icon-plus-o">
<use xlink:href="#icon-plus-o"></use>
</svg> <span i18n="##cvcomponent-addcertificate">J'ajoute un diplôme </span>
</button>
<select2 [data]="certificatesTypes"></select2>
<select2 [data]="exampleData"></select2>
</div>
Here the exampleData select display well but not the certificatesTypes
Don't use this.certificate.push inside for loop. it will not work. instead of you can use something like :
let arrCertificates = [];
response.data.forEach(element => {
const certif = {id: element.id.toString(), text: element.name};
arrCertificates.push(certif);
});
this.certificatesTypes = arrCertificates;

Edit Items in a List Using Modal in Ionic 3

I have created an Array and I'm adding items to the array using Modal.
Now i need to edit the item by selecting it from the list.
please help me with the Code.
How to fetch the item to modal and bring back the edited item in the same place in the list
HOME.HTML
<ion-header>
<ion-navbar>
<ion-title>
Ionic Blank
</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item *ngFor="let grocery of itemsArray">{{grocery}}</ion-item>
</ion-list>
<button ion-button round (click)="addItem()">Add Item</button>
</ion-content>
HOME.TS
export class HomePage {
public itemsArray = [];
newItem: any;
constructor(public navCtrl: NavController, public modalCtrl: ModalController, public navParams: NavParams) {
}
ionViewDidLoad() {
this.newItem = this.navParams.get('data');
this.itemsArray = [
];
}
public addItem() {
let modalPage = this.modalCtrl.create(ModalPage);
modalPage.onDidDismiss(data => {
this.itemsArray.push(data.name
);
});
modalPage.present();
}
}
MODAL.HTML
<ion-header>
<ion-navbar>
<ion-title>Add Item</ion-title>
<ion-buttons end>
<button ion-button (click)="closeModal()">Close</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-list>
<ion-item>
<ion-label>Item</ion-label>
<ion-input type="text" [(ngModel)]="newItem"></ion-input>
</ion-item>
<button ion-button color="secondary" (click)="add()">Add Item</button>
</ion-list>
</ion-content>
MODAL.TS
export class ModalPage {
name:any;
newItem: any;
constructor(public navCtrl: NavController, public viewCtrl: ViewController, public navParams: NavParams) {
}
ionViewDidLoad() {
console.log('ionViewDidLoad ModalPage');
}
public closeModal() {
this.viewCtrl.dismiss();
}
//add() {
// let data = {"name": this.newItem};
// this.viewCtrl.dismiss(data.name)
// }
add() {
let data = {"name": this.newItem};
this.viewCtrl.dismiss(data)
}
}
The code untill now works fine.
I would recommend using alert controller to simplify your code in your use case. If you would need a modal - you can elaborate the code later.
Try this approach:
<ion-header>
<ion-navbar>
<ion-title>
Ionic Blank
</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list *ngFor="let grocery of itemsArray; let i = index">
<ion-item (click)="changeItemName(grocery, i)">{{grocery}}</ion-item>
</ion-list>
<button ion-button round (click)="addItem()">Add Item</button>
</ion-content>
Place iterator on the list and capture "index" per item, so that you could pass that value if particular item from the list is clicked together with actual grocery item name.
In your home.ts:
import { Component } from '#angular/core';
import { NavController, NavParams, AlertController, ViewController } from 'ionic-angular';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public itemsArray = ["milk", "butter", "bread"];
newItem: any;
constructor(public navCtrl: NavController, public alertCtrl: AlertController, public navParams: NavParams) {
}
public changeItemName(currentName, index) {
let alert = this.alertCtrl.create({
title: 'Change grocery item name:',
message: 'current: "' + currentName + '"',
inputs: [
{
placeholder: 'type in a new name'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
},
{
text: 'Confirm',
handler: data => {
if (data[0].length === 0) {
this.itemsArray[index] = currentName;
} else {
this.itemsArray[index] = data[0];
}
}
}
]
});
alert.present();
};
public addItem() {
let index = this.itemsArray.length;
this.changeItemName("New item", index);
}
}
You can use alert controller to show a small pop-up with input field. In the code you will see that we pass parameters to it and we modify list item name OR we add item to the list if change name method was called by addItem method.
Let me know if this is helpful for you.
Here is a working snippet: https://stackblitz.com/edit/ionic-urbtag

Ion-list not refreshing afer model change

I am having a problem with the ion-list, I can list all the items when the app loads for the first time, but when I make any changes to it, adding or removing data, the list isn't updating for the user.
I am using Pouch db to add and remove data for persistence in the app, all the functions are working correctly, it can be confirmed through console.log in the contents or using the fauxton PouchDb extension for chrome.
Resuming, the data is changing, but the view is not reflecting it.
the view code is this notas.html
<ion-content>
<ion-list>
<ion-item-sliding *ngFor="let n of notas">
<ion-item>
<h2>{{n.descricao}}</h2>
<p>URL: {{n.endereco}}</p>
<p>Data de expiração: {{n.vencimento}}</p>
</ion-item>
<ion-item-options side="right">
<button ion-button (click)="editar(n)">
<ion-icon name="paper"></ion-icon>
Editar
</button>
<button ion-button color="danger" (click)="excluir(n)">
<ion-icon name="trash"></ion-icon>
Excluir
</button>
</ion-item-options>
</ion-item-sliding>
</ion-list>
</ion-content>
And the controler code is this notas.ts
...
#Component({
selector: 'page-notas',
templateUrl: 'notas.html'
})
export class NotasPage {
notas: any;
constructor(public navCtrl: NavController, public alertCtrl: AlertController, public pouchDBService: PouchdbProvider) {
//PARA USO DO EXTENSION DO CHROME *POUCHDB Fauxton
(<any>window).PouchDB = PouchDB;
this.notas = [];
}
ionViewDidLoad(){
this.refresh();
}
refresh(){
//console.log(this.notas);
this.notas = [];
this.pouchDBService.getData().then((data) => {
this.notas = data;
console.log(this.notas);
});
// console.log(this.notas);
}
excluir(nota){
let prompt = this.alertCtrl.create({
title: 'Excluir',
message: 'Deseja realmente excluir o registro?',
buttons: [
{
text: 'Cancelar'
},
{
text: 'Excluir',
handler: data => {
this.pouchDBService.delete(nota);
this.notas.pop(nota);
this.refresh();
}
}
]
});
prompt.present();
}
}
...
Not 100% sure on this but usually if the view is not updating, it has to do with the code not running on zone, so:
import { NgZone } from '#angular/core';
...
zone: any = new NgZone({ enableLongStackTrace: false });
And then change your refresh method to:
refresh(){
//console.log(this.notas);
this.notas = [];
this.pouchDBService.getData().then((data) => {
this.zone.run(() => {
this.notas = data;
console.log(this.notas);
});
});
// console.log(this.notas);
}
I believe that should work.

AngularJS Cannot find a differ supporting object '[object Object]' of type 'object' and Parse Query

So when I try to take my data from my parse query and put it in my array I end up with this error Cannot find a differ supporting object '[object Object]' of type 'object'. My Code for the Html and ts file are below. And my model file is also below. Is there a better way to display this data in the list?
Html:
<ion-header>
<ion-navbar>
<ion-title button-right>Trade</ion-title>
<ion-buttons end>
<button ion-button icon-only (click)="addTrade()">
<ion-icon name="add"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content>
<ion-searchbar (ionInput)="getItems($event)"></ion-searchbar>
<ion-list [virtualScroll]="items">
<ion-item *virtualItem="let item">
{{ item.offering }} {{item.needs}}
</ion-item>
</ion-list>
</ion-content>
and my ts file
import { Component } from '#angular/core';
import { NavController, NavParams, AlertController } from 'ionic-angular';
import { Items} from "../../trade-model";
var Parse = require('parse');
/*
Generated class for the Trade page.
See http://ionicframework.com/docs/v2/components/#navigation for more info on
Ionic pages and navigation.
*/
#Component({
selector: 'page-trade',
templateUrl: 'trade.html'
})
export class TradePage {
searchQuery: string = ''
items: Items ={
offering: [],
needs: []
}
constructor(public navCtrl: NavController, public navParams: NavParams, public alertCtrl: AlertController) {
Parse.initialize('blankedout','unused', "blankedout");
Parse.serverURL = 'blankedout';
}
ionViewWillEnter(){
this.initializeItems()
}
ionViewWillLeave(){
}
initializeItems() {
var this_ref = this
var Trade = Parse.Object.extend("Trade")
var query = new Parse.Query(Trade);
query.find({
success: function(trades) {
for (var i = 0; i < trades.length; i++) {
this_ref.items.offering = trades[i].get("offer")
this_ref.items.needs = trades[i].get("wants")
}
}
});
}
}
This is the template/interface
export interface Items{
offering: string[];
needs: string[];
}
items is an object. Ionic virtualScroll requires an array to be passed in.
Do you mean to do:
<ion-list [virtualScroll]="items.offering">
<ion-item *virtualItem="let item">
{{ item}}
</ion-item>
</ion-list>

Resources