How to open date picker explicitly in Ionic 4? - ionic-framework

I want to open ionic date time picker when I click a button(or when i set value in one picker it should open another date time picker).

Nice workaround:
add datetime component and hide it.
attach a reference to it.
make sure to display the value manually since the picker is hidden.
code example attached.
html:
<ion-col (click)="datePicker.open()" width-50>
<ion-icon name="calendar"></ion-icon>
<div>
{{ selected.toDate() | amDateFormat:'DD' }} {{ selected.toDate() | amDateFormat:'MMM' }}, {{ selected.toDate() | amDateFormat:'YYYY'}}
</div>
<ion-item no-lines hidden="true">
<ion-datetime #datePicker
text-center
(ionChange)="dateChanged($event)"
displayFormat="DD MMM, YYYY"
[(ngModel)]="date"></ion-datetime>
</ion-item>
</ion-col>
.ts:
import {Component, ViewChild} from '#angular/core';
import { DateFormatPipe } from 'angular2-moment';
import * as moment from 'moment';
#Component({
templateUrl: './awesome-compo/awesome.html',
pipes: [ DateFormatPipe ]
})
export class AwesomeCompo {
private selected: any = moment();
private date: any = moment().toISOString();
#ViewChild('datePicker') datePicker;
dateChanged(date) {
const { day, month, year } = date;
this.selected.year(year.value).month(month.text).date(day.value);
};
}
For a detailed answer: Full answer

Related

How to pass a ts variable in html page to ts page then perform some calculation and pass it back to html page?

I am trying to take amount to be transacted as input from user deduct it from the wallet of the user and then display the updated wallet. The wallet already is pre-loaded with 100 units of money. But when I run the app only 100 is displayed and the changes are not reflected. what do I do ?
Here is my html code
<ion-row>
<ion-col class="txt2" size="6" text-left >Company<br><ion-text class="bal">Balance & gms</ion-text>
</ion-col>
<ion-col class="text2" size="6" text-right ><ion-item><ion-input type="number" value="{{ wallet }}" [(ngModel)]="wallet" class="ion-text-end"></ion-input>
</ion-item>
</ion-col>
</ion-row>
<ion-item class="transact-display">
<ion-input type="number" placeholder="Enter amount" [(ngModel)]="amount" name="amount"></ion-input>
</ion-item>
<ion-button class="transact" type="submit" expand="block" (click)="transact()">Transact</ion-button>
The ts file
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'app-transaction',
templateUrl: './transaction.page.html',
styleUrls: ['./transaction.page.scss'],
})
export class TransactionPage implements OnInit {
constructor(public router : Router) {}
wallet: number = 100;
amount: number ;
ngOnInit() {
}
transact() {
this.router.navigateByUrl('/congratulation');
this.wallet = this.wallet - this.amount;
return this.wallet;
}
}
Actual behaviour:
No change in the displayed amount. 100 is only displayed even after the Transact button is clicked.
Expected behaviour:
when the user logs in for the 1st time, 100 should be displayed. When the user transacts amount, say 20, 20 should be deducted from 100 and 80 should be displayed.
Angular is 2 way data binding framwwork:
Use Angular interpolation:
.html
<ion-item>
{{wallet}}
</ion-item>
<ion-item class="transact-display">
<ion-input type="number" placeholder="Enter amount" [(ngModel)]="amount" name="amount"></ion-input>
</ion-item>
<ion-button class="transact" type="submit" expand="block" (click)="transact()">Transact</ion-button>
.ts
wallet: number = 100;
amount: number ;
ngOnInit() {
}
transact() {
this.wallet = this.wallet - this.amount; // this will update wallet automatically.
this.router.navigateByUrl('/congratulation');
}

ion-select, ion-input and retrive its value on second page

I am getting the number values from the ion-select and input a number in the ion-input. How can I display the selected value and the input value from the original page to another page?
I am using ionic 4
<ion-item>
<ion-input #user2 type="tel" maxlength="14" minlength="4" [(ngModel)]="numpad"
name="userCount" (keypress)="numberOnlyValidation($event)"></ion-input>
</ion-item>
<ion-item (click)="openSelect()">
<ion-input [(ngModel)]="selectedCode"></ion-input>
</ion-item>
<ion-item style="display: none">
<ion-select #select1 [(ngModel)]="selectedCode">
</ion-select>
</ion-item>
Here's one solution. Assume the input is in home.page and the values will be routed to page2.page.
Update app-routing.module.ts and add a new route
{
path: 'page2/:code/:numpad',
loadChildren: () => import('./page2/page2.module').then( m => m.Page2PageModule)
},
Then you will want to take the values from home.page and navigate to page 2. There are a few different way to do this. In the example below I'm just using ionChange to call a function to route to page2.
home.page.ts
<ion-item>
<ion-input #user2 type="tel" maxlength="14" minlength="4" [(ngModel)]="numpad" name="userCount"></ion-input>
</ion-item>
<ion-item>
<ion-select [(ngModel)]="selectedCode" (ionChange)="valueChangedSoRouteToPage2()">
<ion-select-option *ngFor="let user of users" [value]="user.id">{{user.first + ' ' + user.last}}</ion-select-option>
</ion-select>
</ion-item>
Then in home.page.ts you can do something like this
valueChangedSoRouteToPage2() {
console.log('changed');
console.log(this.selectedCode);
console.log(this.numpad);
this.router.navigateByUrl('/page2/' + this.selectedCode + '/' + this.numpad);
}
Last step - update page2.page.ts
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-page2',
templateUrl: './page2.page.html',
styleUrls: ['./page2.page.scss'],
})
export class Page2Page implements OnInit {
page2Code;
page2Numpad;
constructor(private activatedRoute: ActivatedRoute) { }
ngOnInit() {
this.page2Code = this.activatedRoute.snapshot.paramMap.get("code");
this.page2Numpad = this.activatedRoute.snapshot.paramMap.get("numpad");
console.log('code: ' + this.page2Code);
console.log('numpad: ' + this.page2Numpad);
}
}
Hope this helps.

Ionic 3 : How to make checkboxes behavior like radio-button

I have a list of checkboxes and I want to make them behave like radio button
How can I do this?
I tried using radio button but I am not getting the value of the user input so I dropped the idea of radio button and implement checkbox where i get the proper value & everything is perfect except the multiple checkbox selection I want to remove that
Here is my code:
selectOption(name, isChecked) {
if (isChecked === true) {
this.selectednames.push(name);
} else {
let index = this.removeCheckedFromName(name);
this.selectednames.splice(index, 1);
}
}
removeCheckedFromName(names: String) {
return this.selectednames.findIndex((ref) => {
return ref === names;
});
}
in my HTML
<ion-list>
<ion-list-header>
Choose Your Team
</ion-list-header>
<ion-item *ngFor="let names of name; let i = index">
<ion-label>{{name}}</ion-label>
<ion-checkbox item-left color="secondary" formControlName="name"
(ionChange)="selectOption(name, $event.checked)">
</ion-checkbox>
</ion-item>
</ion-list>
Any advices is highly appreciated
checkbox-stovr.page.html
<ion-header>
<ion-toolbar>
<ion-title>checkbox-stovr</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-list-header>
Choose Your Team
</ion-list-header>
<ion-item *ngFor="let name of names; let i = index">
<ion-label>{{ name['name'] }}</ion-label>
<ion-checkbox [(ngModel)]="name['isChecked']" (click)="toggle(name)">
</ion-checkbox>
</ion-item>
</ion-list>
</ion-content>
CheckboxStovrPage
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-checkbox-stovr',
templateUrl: './checkbox-stovr.page.html',
styleUrls: ['./checkbox-stovr.page.scss'],
})
export class CheckboxStovrPage implements OnInit {
names = [{ name: 'a' }, { name: 'b' }, { name: 'c' }, { name: 'd' },];
public selected: string;
constructor() { }
ngOnInit() {
}
public toggle(selected) {
for (let index = 0; index < this.names.length; index++) {
if (this.names['name'] != selected['name'])
this.names[index]['isChecked'] = null;
}
}
}
Do you want only one value selected at a time ??

Pass data from home.html to home.ts

I'm new to Ionic and I would like to know how I can pass data that is in between the <p></p> HTML tag to my home.ts file. I have tried doing getElementById but that doesn't seem to work. Also ViewChild but with zero results. I'd like to have some help concerning this question.
From .ts -> html :
.ts-> varString : String = "Hallo world";
html-> {{varString}}
From html -> .ts depends of html tag
Ex. <input type=“text” name=“username” [(ngModel)]=“username”>
username is username : String = ""; and it changes avry time you update the input. Similar to other html tags. You can also get elements by id or class using Element of ionic angular
there is many way to pass data between html and ts, but you must have good understand about MVC design pattern. the MVC is the reason of why google introduced angular.
in angular (engine of ionic), your View(html in your project) knows everything about controller(ts file).
***** home.ts********
public MyName:string="jon";
MyFunc1()
{
alert(this.MyName);
}
MyFunc2()
{
this.MyName="other name";
alert(this.MyName);
}
*****home.html*******
<input type="text" [(ngModel)]="MyName" >
<p>{{MyName}}</p>
<button ion-button (click)="MyFunc1()" >MyFunc1</button>
<button ion-button (click)="MyFunc2()" >MyFunc2</button>
.
.
.
if you change the value of MyName in ts, then it will change automatically in html and also if you change you input value (that it is binded to MyName) it will change the MyName value in model (in ts).
Selecting DOM in ionic isn't a right way to change models value.
Taking the simple example of a Login page,
<ion-item>
<ion-label floating color="primary">Registered Email ID</ion-label>
<ion-input [(ngModel)]="login.email" name="email" type="text" #email="ngModel" spellcheck="false" autocapitalize="off"
required>
</ion-input>
</ion-item>
<ion-item>
<ion-label floating color="primary">Passcode</ion-label>
<ion-input [(ngModel)]="login.passcode" name="password" type="password" #password="ngModel" required>
</ion-input>
</ion-item>
The .ts code for this would be:
login= { username: '', email:'', mobile:'', passcode:'' };
That is literally it!
You can also go about without the login object and can declare variables like
username: any
email: any
and so on; and directly reference them in the html as
[(ngModel)]="username"
Hope it helps!
First try to understand that when you are working on Ionic, you are working on Angular but not Core Javascript.
and here is simple example that may help
home.html
import {Component} from '#angular/core';
import {NavController, AlertController} from 'ionic-angular';
#Component({
templateUrl: 'build/pages/home/home.html'
})
export class HomePage {
name: string;
constructor(public navCtrl: NavController, private alertController: AlertController) {
}
showName() {
console.log(this.name);
let alert = this.alertController.create({
title: 'Hello ' + this.name + '!',
buttons: ['OK']
});
alert.present();
}
}
home.ts
<ion-header>
<ion-navbar>
<ion-title>
Ionic Blank
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-label>{{ name }}</ion-label>
<ion-input [(ngModel)]="name"></ion-input>
<button (click)="showName()">Click Me</button>
</ion-content>

Ionic 2: View does not update based on model change

I have a very simple page with a couple of controls.
My issue is that the page does not pickup changes to the model when the icon in upper right corner is clicked. This toggles the showFilterPane variable, which again should show or hide a div based on *ngIf="showFilterPane".
I have another page just like this one working, and I can not figure out why this isn't.
Any tips?
(I've tried using the ChangeDetectorRef.detectChanges(); which works, but then the rangeslider will not work. The draggable point doesn't update, or does not move to where you tap.)
The page:
<ion-header>
<ion-navbar>
<ion-title>MY AO</ion-title>
<ion-buttons end>
<button ion-button (click)="toggleFilterPane()" icon-only>
<ion-icon name="options"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content>
<div class="container">
<div class="left">
<div *ngIf="isSearching" class="spinner-container">
<ion-spinner></ion-spinner>
</div>
<!-- put content here -->
</div>
<div class="right" *ngIf="showFilterPane">
<ion-list inset>
<ion-list-header>BANA</ion-list-header>
<ion-item>
<ion-select multiple="true" [(ngModel)]="woTrackFilter">
<ion-option>1</ion-option>
<ion-option>2</ion-option>
<ion-option>3</ion-option>
<ion-option>4</ion-option>
<ion-option>5</ion-option>
</ion-select>
</ion-item>
</ion-list>
<ion-list inset>
<ion-list-header>TEKNIKSLAG</ion-list-header>
<ion-item>
<ion-select multiple="true" [(ngModel)]="woDisciplineFilter">
<ion-option>Signal</ion-option>
<ion-option>Bana</ion-option>
<ion-option>EL</ion-option>
<ion-option>Tele</ion-option>
</ion-select>
</ion-item>
</ion-list>
<ion-list inset>
<ion-list-header>DAGAR</ion-list-header>
<ion-item>
<ion-range min="10" max="80" step="4" [(ngModel)]="woDaysFilter">
<ion-label range-left>10</ion-label>
<ion-label range-right>80</ion-label>>
</ion-range>
</ion-item>
</ion-list>
<button ion-button (click)="doSearch()">Search</button>
</div>
</div>
</ion-content>
The component:
import { Component } from '#angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { WorkOrderDashboardPage } from "../work-order-dashboard/work-order-dashboard";
#Component({
selector: 'page-work-order-list',
templateUrl: 'work-order-list.html'
})
export class WorkOrderListPage {
private isSearching: boolean = false;
private showFilterPane: boolean=false;
private woTrackFilter: string[];
private woDisciplineFilter: string[];
private woDaysFilter: number;
constructor(public navCtrl: NavController, public navParams: NavParams) {
// Initialize storage providers here
}
ionViewDidLoad() {
console.log('ionViewDidLoad WorkOrderListPage');
}
toggleFilterPane(): void {
this.showFilterPane = !this.showFilterPane;
}
viewWorkOrder(event, workOrder): void {
this.navCtrl.push(WorkOrderDashboardPage, { workOrder: workOrder });
}
doSearch(): void {
console.log(this.woTrackFilter);
console.log(this.woDisciplineFilter);
console.log(this.woDaysFilter);
}
}
UPDATE: Found workaround
I tried creating a separate app, where the exact same code is working. That lead me to think something wasn't right on the LoginPage, the page that called setRoot() to the above page.
The login code looked like this:
WLAuthorizationManager.login("UserLogin", data).then(() => {
// Success
console.log("Logged in");
this.navCtrl.setRoot(WorkOrderListPage);
},
(err) => {
// failed
console.error(err);
this.showError("Username or password is incorrect");
})
I then figured it might be some Zone issue, and wrapped the setRoot call in zone.run() like this:
WLAuthorizationManager.login("UserLogin", data).then(() => {
// Success
console.log("Logged in");
this.zone.run(() =>
this.navCtrl.setRoot(WorkOrderListPage)
);
},
(err) => {
// failed
console.error(err);
this.showError("Username or password is incorrect");
})
After that the view started to respond as expected. I feel this is a bit of a hack. Can someone shed some light as to what is happening here?
Seems like you are basically using ngZone to make sure Angular knows you changed things so it will reload that part of the DOM to reflect the changes. I don't feel like it's a hack, because you are just making sure that it works as intended.
Angular 2 has some optimization features that help make your app run smoother and one of those is avoiding DOM updates whenever and wherever possible. By using zones (or ngZones) you are basically telling Angular "pay attention to this part, it changes and I need that change to be reflected in the DOM".
I've run into that sort of problem before myself and using zones is usually your best bet. Got into situations where a part of the interface would be stuck unless you touched a button or somesuch.
Another workaround (at least for range sliders) is using the AppllicationRef tick() method, which forces a DOM update. More info about it here.