Ionic-2: Cannot read the property 'open' of undefined - javascript

I'm creating an ionic-2 project, where I've a button at the right bottom. My concept is, when I click the button, the time picker should open. I've to select my time and click done.
This is how I've tried:
HTML:
<ion-header>
<ion-navbar color="primary">
<ion-title>Alarms</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-card *ngFor="let alarms of serAlarm">
<ion-card-header>
{{alarms.id}}
<ion-toggle value="foo" checked="true"></ion-toggle>
</ion-card-header>
<ion-card-content>
<ion-checkbox (click)="clickRepeat()"></ion-checkbox> Repeat
<div class="hide">
</div>
</ion-card-content>
<ion-card-content class="top0">
{{alarms.hour}}:{{alarms.minute}}
</ion-card-content>
</ion-card>
<ion-datetime #dateTime displayFormat="HH:mm" pickerFormat="HH:mm" [(ngModel)]="dateTimeModel" (ionChange)="onTimeChange()"></ion-datetime>
<ion-fab right bottom>
<button ion-fab color="primary" (click)="opentime()">
<ion-icon name="add"></ion-icon>
</button>
</ion-fab>
</ion-content>
TS:
import { Component, ViewChild } from '#angular/core';
import { NavController} from 'ionic-angular';
#Component({
selector: 'page-alarm',
templateUrl: 'alarm.html'
})
export class AlarmPage {
time: string = '00:00';
serAlarm = [];
constructor(public navCtrl: NavController) { }
#ViewChild('dateTime') sTime;
opentime(){
this.sTime.open();
}
onTimeChange() {
var res = this.time.toString().split(":");
this.serAlarm.push({
id: "0",
description: "",
hour: res[0],
minute: res[1],
repeat: "0",
action: "0",
active: "1"
});
}
}
Here, everything works fine. But, when I click the + button, I get the error Cannot read the property 'open' of undefined. I guess, the problem is in <ion-datetime> line. But, I can't figure what's wrong. Can someone help me with it? What should I change?

In order to select the element you need to give the correct selector, if you want it to be dateTime then change the element to:
<ion-datetime #dateTime displayFormat="HH:mm" pickerFormat="HH:mm" [(ngModel)]="dateTimeModel" (ionChange)="onTimeChange()"></ion-datetime>
Note that I've changed the ngModel since they had the same name reference.
Now you can get hold of the element with #ViewChild('dateTime') sTime;

Related

angular4- show element only when texbox is focused

I'm trying to show an element on my page when a textbox is focused.
HTML
<ion-header>
<ion-navbar color="primary">
</ion-navbar>
<ion-toolbar>
<ion-row >
<ion-col>
<ion-searchbar placeholder="Search Account Number" [(ngModel)]="searchInput"> </ion-searchbar>
</ion-col>
<ion-col col-2>
<ion-icon (click)="searchCustomer()" ion-item name="arrow-forward"></ion-icon>
</ion-col>
</ion-row>
<p align="right" *ngIf="searchInput.length > 0">
<span style="color:gray;padding:5px">Switch to Advance Search</span>
</p>
</ion-toolbar>
</ion-header>
JavaScript
export class AppHomePage {
searchInput: any;
searchResults: any;
constructor(public navCtrl: NavController,
public loadingCtrl: LoadingController,
public toastCtrl: ToastController,
public http: Http,
public alertCtrl: AlertController) {
this.searchResults = [];
}
}
With my script when the page loads i get this error:
Cannot read property 'length' of undefined
Option 1:
If you haven't initialised seachInput = '' then do it first.
Option 2: User (input) event and get length when user enter any data into text box.
<ion-searchbar placeholder="Search Account Number" (input)="getSeachData($event)" [(ngModel)]="searchInput"> </ion-searchbar>
In your .ts file.
// First set variable above constructor.
searchFlag : boolen = false;
getSeachData(event){
this.searchFlag = true ? event.target.value.length > 0 : false;
}
In your HTML file.
<p align="right" *ngIf="searchFlag">
<span style="color:gray;padding:5px">Switch to Advance Search</span>
</p>
In this way you can do what you want. But Still I suggest to go with the first option. If it's not work well then go with second option.
Hope for the best.
You could use ionFocus event to achieve what you want.
HTML
<ion-header>
<ion-navbar color="primary">
</ion-navbar>
<ion-toolbar>
<ion-row >
<ion-col>
<ion-searchbar placeholder="Search Account Number" [(ngModel)]="searchInput"> </ion-searchbar>
</ion-col>
<ion-col col-2>
<ion-icon (click)="searchCustomer()" (ionFocus)="showSwitchAdvanceSearch()" ion-item name="arrow-forward"></ion-icon>
</ion-col>
</ion-row>
<p align="right" *ngIf="showSwitchAdvanceSearch">
<span style="color:gray;padding:5px">Switch to Advance Search</span>
</p>
</ion-toolbar>
</ion-header>
Typescript
export class AppHomePage {
searchInput: any;
searchResults: any;
showSwitchAdvanceSearch = false;
constructor(public navCtrl: NavController,
public loadingCtrl: LoadingController,
public toastCtrl: ToastController,
public http: Http,
public alertCtrl: AlertController) {
this.searchResults = [];
}
showSwitchAdvanceSearch() {
this.displaySwitchAdvanceSearch = true;
}
}

ionic 2 /3 ; change image src tag when Onclick

I have ionic page that have an image with 100% width and 100% height, I want to change the image source when I click on it.
this is the html source :
<ion-content>
<ion-img class="map" src="img/map.jpg" (click)="changeView()"></ion-img>
<ion-icon class="icon-bonfire" name="ios-bonfire"></ion-icon>
<ion-icon class="icon-heart" name="md-heart"></ion-icon>
<ion-icon class="icon-nuclear" name="md-nuclear"></ion-icon>
<ion-fab top right>
<button ion-fab color="whitecolor"><ion-icon class="calandaricon" name="md-calendar"></ion-icon></button>
</ion-fab>
<ion-fab top left>
<ion-searchbar> </ion-searchbar>
</ion-fab>
<ion-fab bottom right class="fablocate">
<button ion-fab color="whitecolor"><ion-icon class="locateicon" name="md-locate"></ion-icon></button>
</ion-fab>
<ion-fab (click)="ListParrots();" bottom left class="linklist">
<ion-img class="parrot-list-link" src="img/citydirty.jpg"></ion-img>
</ion-fab>
</ion-content>
ts source code is below :
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import {ParrotListPage } from '../parrot-list/parrot-list';
/**
* Generated class for the MapPage page.
*
* See https://ionicframework.com/docs/components/#navigation for more info on
* Ionic pages and navigation.
*/
#IonicPage()
#Component({
selector: 'page-map',
templateUrl: 'map.html',
})
export class MapPage {
images: String[] = Array("img//map.jpg", "img/map1.jpg");
constructor(public navCtrl: NavController, public navParams: NavParams) {
}
changeView(){
}
ionViewDidLoad() {
console.log('ionViewDidLoad MapPage');
}
ListParrots(){
this.navCtrl.push(ParrotListPage);
}
}
can some one help please to complete all the function? thank !
Change your template:
<ion-img class="map" [src]="picToView" (click)="changeView()"></ion-img>
And declare a variable in the class:
picToView:string="img/map.jpg"; // always instatiate with a valid value
And changeView:
changeView(){
this.picToView=.....
}
Regards
Tom

Scroll not working when from Popover

I am using Ionic 2.
I have a page, that scrolls perfectly when I navigate to the page from another page. However, when I navigate to the page from a Popover, the page displays, but I am unable to scroll.
Any ideas please?
Navigate to page from Popover and other page is the same:
this.nav.push(CategoryPage, {
employeeModel: this.employeeModel,
fromSearch: true
});
page:
<ion-header>
<ion-navbar>
<ion-title>{{categoryModel.name}}</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<center>
<ion-spinner icon="android" *ngIf="loading"></ion-spinner>
<div class="category-text animate-show">
<div class="select-text" *ngIf="getSelected().length === 0">Select the Roles</div>
<p class="item-selected-row" *ngFor="let subcategory of getSelected()">
<img class="item-stable" id="icon-image-{{subcategory.id}}" src="{{subcategory.icon}}" (click)="toggleItem(subcategory)"/>
</p>
</div>
</center>
<ion-row *ngFor="let trio of getTriples()">
<ion-col *ngFor="let item of trio">
<center>
<div class="row responsive-md">
{{ formatSubCategories(item) }}
<img class="item-stable-large" id="icon-image-{{item.id}}" src="{{item.icon}}" (click)="toggleItem(item)"
[class.item-selected]="isSubCategoryModelItemInArray(item) > -1" />
<p>{{item.name}}</p>
</div>
</center>
</ion-col>
</ion-row>
<ion-buttons>
<button (click)="next()" block round class="form-button-text">Next</button>
</ion-buttons>
</ion-content>
popover
import {Component, ViewChild, ElementRef} from '#angular/core';
import {App, PopoverController, NavController, Content, NavParams} from 'ionic-angular';
import {NgForm} from '#angular/forms'
import { MapPage } from '../map/map';
import { CategoryPage } from '../category/category';
import { EmployeeModel } from '../model/employeeModel';
#Component({
template: `
<ion-content padding id="search-popover">
<ion-list>
<ion-row>
<ion-col>
<center>
<div id="pinButton"><button class="search-popover-button" (click)="presentFilterMap()" danger><ion-icon class="search-popover-icon" name="pin"></ion-icon></button></div>
<p>Location</p>
</center>
</ion-col>
<ion-col>
<center>
<div id="pinButton"><button class="search-popover-button" (click)="presentFilterCategories()" primary><ion-icon class="search-popover-icon" name="happy"></ion-icon></button></div>
<p>Sectors</p>
</center>
</ion-col>
</ion-row>
</ion-list>
</ion-content>
`
})
export class SearchPopOverPage {
private nav: NavController = null;
private employeeModel: EmployeeModel = null;
constructor(private navParams: NavParams, nav: NavController) {
this.nav = nav;
this.employeeModel = navParams.get('employeeModel');
}
ngOnInit() {
}
presentFilterMap(event: Event) {
this.nav.push(MapPage, {
employeeModel: this.employeeModel,
fromSearch: true
});
}
presentFilterCategories(event: Event) {
this.nav.push(CategoryPage, {
employeeModel: this.employeeModel,
fromSearch: true
});
}
}
Here is the solution.
presentFilterCategories(event: Event) {
this.viewCtrl.dismiss().then(() => {
this.nav.push(CategoryPage, {
ev: event,
employeeModel: this.employeeModel,
fromSearch: true
})
});
}

angular 2 reusability in ionic 2 with template overriding

I have some angular 2 components that work fine for a web app.
So, I would want to reuse some of them in an ionic 2 application but without rewriting things.
Ionic has special directives, example: lists. I would have liked to be able to reuse my components by "adding" the ionic directives on top of it.
Ionic syntax:
<ion-list>
<ion-item *ngFor="let product of products">
{{product.name}}
</ion-item>
</ion-list>
Example of angular components:
*Main ionic page:
#Component({
template: `
<ion-header>
<ion-navbar>
<button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>Products</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<product-list [products]="products"></product-list>
</ion-content>
`,
directives: [ProductListComponent],
providers: [ProductService]
})
export class ProductsPage implements OnInit{
products;
constructor(
private navCtrl: NavController,
private productService:ProductService) {
}
ngOnInit() {
this.productService.all().subscribe(data => {
this.products = data;
});
}
}
A list of products:
#Component({
selector: 'product-list',
template: `
<ul>
<li *ngFor="let product of products">
<product-list-element [product]="product"></product-list-element>
</li>
</ul>
`,
directives: [ProductListElementComponent]
})
export class ProductListComponent {
#Input() products;
}
An element of the list
#Component({
selector: 'product-list-element',
template: `
<div>
<h3>{{product.name}}</h3>
</div>
`
})
export class ProductListElementComponent {
#Input() product;
}
Here in the example, there is no much logic so rewriting the template is ok but in the real case...
I don't know how to handle this, I'm new in angular 2.
I think the beginning of an answer will be to hide less things and expose more peace of the template but maybe someone already done this before.
Maybe like so:
<ion-list>
<ion-item *ngFor="let product of products">
<ion-icon name="leaf" item-left></ion-icon>
<product-list-element [product]="product">
<product-title [title]="product.title"></product-title>
</product-list-element>
</ion-item>
</ion-list>
Thank you in advance :)

Order list ionic 2

I have a page with one list from a JSON file. What I want to do it's to add an order by funcionality. I don't understand yet if I need to use #Pipe or if there is a simpler way.
I'm planning to do it in a modal page.
Thanks in advance any help will be appreciated.
modalpage.html:
<ion-toolbar danger>
<ion-buttons start>
<button (click)="close()">
<ion-icon ios="ios-close" md="md-close"></ion-icon>
</button>
</ion-buttons>
<ion-title text-center>
Ajustes
</ion-title>
<ion-buttons end>
<button (click)="applyFilters()">
<ion-icon ios="ios-checkmark" md="md-checkmark"></ion-icon>
</button>
</ion-buttons>
</ion-toolbar>
<ion-content padding class="rojo">
<h2 text-center>Ordenar resultados por:</h2>
</ion-content>
modalpage.js
import {Page, NavController,ViewController} from 'ionic-angular';
#Page({
templateUrl: 'build/pages/ajustes-listado/ajustes-listado.html',
})
export class AjustesListadoPage {
static get parameters() {
return [[NavController],[ViewController]];
}
constructor(nav, viewController) {
this.nav = nav;
this.viewCtrl = viewController;
}
close(data) {
this.viewCtrl.dismiss(data);
}
applyFilters(){
console.log('aplicando filtros a la lista');
this.close();
}
}
list.html
<ion-navbar *navbar danger>
<ion-title text-center>Listado</ion-title>
<ion-buttons start *ngIf="buscar==false">
<button (click)="search()">
<ion-icon ios="ios-search" md="md-search"></ion-icon>
</button>
</ion-buttons>
<ion-buttons end>
<button (click)="options()">
<ion-icon ios="ios-options" md="md-options"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
<ion-content class="listado">
<ion-list [virtualScroll]="vets">
<button ion-item text-wrap *virtualItem="let vet" (click)="goToDetails(vet)">
<ion-avatar item-left>
<!-- <ion-img [src]="vet.img || defaultImg"></ion-img> -->
<img src="{{vet.img}}" onError="this.src='./files/gmaps.png';" />
</ion-avatar>
<h2>{{vet.nombre}}</h2>
<p>Direccion: {{vet.direccion}}</p>
</button>
</ion-list>
</ion-content>
list.js
import {DetallesPage} from '../detalles/detalles';
import {OnInit} from '#angular/core';
import {Page, NavController, Platform, NavParams, Modal} from 'ionic-angular';
import {MiServicio} from '../../providers/mi-servicio/mi-servicio';
import {AjustesListadoPage} from '../ajustes-listado/ajustes-listado';
#Page({
templateUrl: 'build/pages/listado/listado.html',
providers:[MiServicio]
})
export class ListadoPage {
static get parameters() {
return [[NavController],[Platform],[MiServicio]];
}
constructor(nav,platform, miServicio) {
this.nav = nav;
this.platform = platform;
this.miServ = miServicio;
this.ngOnInit();
}
ngOnInit() {
this.miServ.getVets().subscribe(
data => this.vets = data
);
}
}
Angular2 doesn't provide the orderBy filter (now "pipe") like angular 1 does.
Angular does not ship with pipes for filtering or sorting lists. Developers familiar with Angular 1 know these as filter and orderBy. There are no equivalents in Angular 2.
refer: https://angular.io/docs/ts/latest/guide/pipes.html#!#no-filter-pipe
You'll need to sort the items in your component. The best option is always sort them on the server-side, but if you know there's only a few items or you really want to sort on the client-side, you can use the array.sort() method.
Examples and documentation:
http://www.w3schools.com/jsref/jsref_sort.asp
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
You said you have the list in a JSON file, so it's a persistent data isn't it?
Take a look at this: Sorting with map
I think this will be the best option for you.

Categories