How does ion-toggle work - javascript

The Ionic 2 Documentation doesn't really explain on how to use ion-toggle. I would like to take the values from the On Checkbox/Toggle to next page/state.
Please help in understanding.
TypeScript
import { Component } from '#angular/core';
import { NavController, NavParams, LoadingController } from 'ionic-angular';
import { Apis } from '../../app/apis';
import { BookingConfirmationPage } from '../booking-confirmation/booking-confirmation';
#Component({
selector: 'page-booking-enhancement',
templateUrl: 'booking-enhancement.html',
providers: [Apis]
})
export class BookingEnhancementPage {
constructor(public navCtrl: NavController, public navParams: NavParams, public loadingCtrl: LoadingController, public Apis: Apis ) {
}
}
HTML
<ion-grid>
<ion-row *ngFor="let item of extra" class="row-extra">
<ion-col width-10>
<ion-toggle class="switcher display-block" color="secondary"></ion-toggle>
</ion-col>
<ion-col width-67 class="description">{{ item.description }}</ion-col>
<ion-col width-23 style="text-align: right;">
<div class="rate text-center display-block">${{ item.rate }}</div>
<div class="qty text-center display-block"><input type="number" class="text-center"/></div>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-col width-100 class="text-center"><button type="submit" class="continue" (click)="ContinueBookingConfirmation()">Continue</button></ion-col>
</ion-col>
</ion-row>
</ion-grid>

Related

Ionic 5 / Angular 8 toggle a div on clicking outside

I have a settings screen with 4 radio buttons. If I click on any of the radio button a success message should be displayed and if I click anywhere else the message should be hidden.
Here is the code:
settings.component.html:
<ion-content>
<div class="flex-container">
<ion-card>
<div class="message">
<div class="message-inner" *ngIf="isMessageDisplay">
<ion-icon name="checkmark"></ion-icon>
<p>Success message</p>
</div>
</div>
<div class="home-screen">
<ion-card-header>
<ion-card-title class="ion-text-center">Select the home page to display</ion-card-title>
</ion-card-header>
<ion-card-content class="home-screen-buttons">
<ion-list class="radio-buttons">
<ion-radio-group name="homeButtons"
>
<ion-row>
<ion-col size="6">
<ion-item lines="none">
<ion-label>home 1</ion-label>
<ion-radio [value]="home.home1"
(ionSelect)="home1()"
color="secondary"
></ion-radio>
</ion-item>
</ion-col>
<ion-col size="6">
<ion-item lines="none">
<ion-label color="lightgray">home 2</ion-label>
<ion-radio [value]="home.home2"
(ionSelect)="home2()"
color="secondary"
></ion-radio>
</ion-item>
</ion-col>
</ion-row>
</ion-radio-group>
</ion-list>
</ion-card-content>
</div>
<div class="products">
<ion-card-header>
<ion-card-title class="ion-text-center">Select the product to display</ion-card-title>
</ion-card-header>
<ion-card-content class="products-buttons">
<ion-list class="radio-buttons">
<ion-radio-group name="productButtons">
<ion-row>
<ion-col size="6">
<ion-item lines="none">
<ion-label>Product 1</ion-label>
<ion-radio [value]="product.product1"
(ionSelect)="product1()"
color="secondary"></ion-radio>
</ion-item>
</ion-col>
<ion-col size="6">
<ion-item lines="none">
<ion-label color="lightgray">Product 2</ion-label>
<ion-radio [value]="product.product2"
(ionSelect)="product2()"
color="secondary"></ion-radio>
</ion-item>
</ion-col>
</ion-row>
</ion-radio-group>
</ion-list>
</ion-card-content>
</div>
</ion-card>
</div>
</ion-content>
settings.component.ts:
import { Component, ElementRef, HostListener, OnDestroy, OnInit } from '#angular/core';
import { Store } from '#ngrx/store';
import { Subscription } from 'rxjs';
#Component({
selector: 'app-settings-menu',
templateUrl: './settings-menu.page.html',
styleUrls: ['./settings-menu.page.scss'],
})
export class SettingsMenuPage implements OnInit, OnDestroy {
isMessageDisplay: boolean = false;
subscriptions$: Subscription[] = [];
constructor(
private store: Store<any>,
private elemRef: ElementRef
) {
}
ngOnInit() {
}
#HostListener('document:click', ['$event.target'])
onClickOutside(targetElement) {
const target = this.elemRef.nativeElement.querySelector('ion-radio');
if (targetElement.tagName != target.tagName)
this.isMessageDisplay= false;
}
home1() {
// some other logic
this.isMessageDisplay= true;
}
home2() {
// some other logic
this.isMessageDisplay= true;
}
product1() {
// some other logic
this.isMessageDisplay= true;
}
product2() {
// some other logic
this.isMessageDisplay = true;
}
ngOnDestroy() {
this.subscriptions$.forEach(subscription => subscription.unsubscribe());
}
}
The above code does the task well during development when I run ionic serve command. But once I build the code for browser using ionic cordova build browser --prod --release and deploy it in some server then success message does not toggle right away, it takes much time when I click anywhere else in the screen.
Please help!
The porblem was in the HostListener. Instead of using #HostListener('document:click', ['$event.target']) I used #HostListener('click', ['$event.target']) and removed document. This solved the problem I had during the production. I don't know the exact reason why this happened.

How to open component content into bootstrap modal?

I have component that i want to inject into modal window using ng bootstrap features so i have imported modules into app also added into entrypoints as suggested in ng-bootstrap docs its giving me little hard time. what is correct approach basically i am calling modal from existing component and that component content should load into modal window. any help will be appreciate.
modal.component.ts
import {Component, Input} from '#angular/core';
import {NgbModal, NgbActiveModal} from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'ngbd-modal-content',
template: `
<div class="modal-header">
<h4 class="modal-title">Hi there!</h4>
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Hello, {{name}}!</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-dark" (click)="activeModal.close('Close click')">Close</button>
</div>
`
})
export class NgbdModalContent {
#Input() name;
constructor(public activeModal: NgbActiveModal) {}
}
detail.component.ts
import { Component, OnInit,Pipe, PipeTransform, EventEmitter,Input, Output,OnChanges, SimpleChanges } from '#angular/core';
import {NgbModal,NgbActiveModal} from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'app-detail',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.css'],
})
export class DetailComponent implements OnChanges{
constructor(private detailService: DetailService,private ngbModal: NgbModal) {};
onClick(evt){
const modalRef = this.ngbModal.open(Component);
}
}
detail.component.html
<div class="card card-outline-info">
<div class="card-header bg-info"><h5>Detail</h5><button (click)="onClick($event)"></button></div>
<div class="card-block">
<div class="table-responsive" style="cursor: pointer">
<generic-table [gtClasses]="'table-hover'" #myCustomTable [gtSettings]="secondConfigObject.settings" [gtFields]="secondConfigObject.fields" [gtData]="secondConfigObject.data"></generic-table>
</div>
</div>
</div>
app.module.ts
import { NgbModule,NgbActiveModal } from '#ng-bootstrap/ng-bootstrap';
import { NgbdModalContent } from './NgModal/modal.component';
#NgModule({
declarations: [
AppComponent,
StreamComponent,
SearchComponent,
DetailComponent,
SlaChartComponent,
NgbdModalContent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpClientModule,
HttpModule,
ChartsModule,
BrowserAnimationsModule,
NgbModule.forRoot()
],
providers: [StreamService,DatePipe,
SearchService,
DetailService,
ChartService,AuthService,NgbActiveModal,
{provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true}],
entryComponents: [NgbdModalContent,DetailComponent],
bootstrap: [AppComponent]
})
Try this, I'm not a fan of your modal.component.ts file so scrap that and remove the NgbdModalContent from your app.module.ts
yourModal.component.html
<ng-template #theModal let-c="close" let-d="dismiss">
<div class="modal-header">
<h4 *ngIf="type == 0" class="modal-title">Header</h4>
<button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Hello, {{name}}!</p>
</div>
<div class="modal-footer">
<button type="button" id="cancel-edit-btn" class="btn btn-primary" (click)="c('Close click')">Cancel</button>
</div>
</ng-template>
yourModal.component.ts
import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ViewChildren, ElementRef, Renderer2 } from '#angular/core';
import { NgbModal } from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'app-custom-modal',
templateUrl: './yourModal.component.html',
styleUrls: ['./yourModal.component.scss']
})
export class EditNotesComponent implements OnInit {
#Input() name: string;
#ViewChild('theModal') theModal: ElementRef;
constructor(private modalService: NgbModal) {}
ngOnInit() {
}
showModal() {
this.modalService.open(this.theModal, { size: 'sm', backdrop: 'static'});
}
}
detail.component.html
<div class="card card-outline-info">
<div class="card-header bg-info"><h5>Detail</h5><button (click)="yourCustomModal.showModal()"></button></div>
<div class="card-block">
<div class="table-responsive" style="cursor: pointer">
<generic-table [gtClasses]="'table-hover'" #myCustomTable [gtSettings]="secondConfigObject.settings" [gtFields]="secondConfigObject.fields" [gtData]="secondConfigObject.data"></generic-table>
</div>
</div>
</div>
<app-custom-modal #yourCustomModal [name]="name"></app-custom-modal>
detail.component.ts
import { Component, OnInit,Pipe, PipeTransform, EventEmitter,Input, Output,OnChanges, SimpleChanges } from '#angular/core';
#Component({
selector: 'app-detail',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.css'],
})
export class DetailComponent implements OnChanges{
name: string;
constructor(private detailService: DetailService) {
this.name = 'John Doe';};
}

Angular Material - Collapse inactive steps of Stepper

I have a Stepper from #Angular/Material and it looks great. However, I see many example that have only the current step opened up. I would like this functionality. All inactive steps should be closed.
[EDIT]: Just added in the HTML and TS file.
Component HTML File
<img width="350px" align="middle" mat-card-image src="../assets/Icon_Rev8.png" alt="Logo">
<mat-card-content>
<mat-tab-group mat-stretch-tabs [selectedIndex]="0" dynamicHeight=true>
<mat-tab label="Login">
<form>
<mat-form-field class="sameWidth">
<input matInput style="width:100%;" placeholder="Username">
</mat-form-field>
<mat-form-field class="sameWidth">
<input matInput style="width:100%;" placeholder="Password">
</mat-form-field>
</form>
<button class="sameWidth" mat-raised-button color="primary">Login</button>
<button class="sameWidth" mat-button color="primary">Forgot Password?</button>
</mat-tab>
<mat-tab label="Register">
<mat-progress-spinner mode="indeterminate"></mat-progress-spinner>
<mat-vertical-stepper [linear]=true>
<mat-step [stepControl]="firstFormGroup">
<form [formGroup]="firstFormGroup">
<ng-template matStepLabel>Fill out your name</ng-template>
<mat-form-field>
<input matInput placeholder="Last name, First name" formControlName="firstCtrl" required>
</mat-form-field>
<div>
<button mat-button matStepperNext>Next</button>
</div>
</form>
</mat-step>
<mat-step [active]="true" [stepControl]="secondFormGroup">
<form [formGroup]="secondFormGroup">
<ng-template matStepLabel>Fill out your address</ng-template>
<mat-form-field>
<input matInput placeholder="Address" formControlName="secondCtrl" required>
</mat-form-field>
<div>
<button mat-button matStepperPrevious>Back</button>
<button mat-button matStepperNext>Next</button>
</div>
</form>
</mat-step>
<mat-step>
<ng-template matStepLabel>Done</ng-template>
You are now done.
<div>
<button mat-button matStepperPrevious>Back</button>
</div>
</mat-step>
</mat-vertical-stepper>
<!--<form>
<table cellspacing="0">
<tr>
<td>
<mat-form-field>
<input style="width: 40%;" matInput placeholder="First Name">
</mat-form-field>
</td>
<td>
<mat-form-field>
<input style="width: 40%;" matInput placeholder="Last name">
</mat-form-field>
</td>
</tr>
</table>
<mat-form-field style="width:100%;">
<input matInput placeholder="Password">
</mat-form-field>
</form>-->
<mat-checkbox style="z-index: 1000;" color="primary">I Agree to the Terms and Conditions</mat-checkbox>
<button class="sameWidth" mat-raised-button color="primary">Register</button>
</mat-tab>
</mat-tab-group>
</mat-card-content>
Component TS File
import { Component, OnInit, ViewEncapsulation, Inject } from "#angular/core";
import {
MatIconRegistry,
MatDialog,
MatDialogRef,
MAT_DIALOG_DATA
} from "#angular/material";
import { DomSanitizer } from "#angular/platform-browser";
import { HttpClientModule, HttpClient } from "#angular/common/http";
import { FormBuilder, FormGroup, Validators } from "#angular/forms";
#Component({
selector: "app-login",
templateUrl: "login.component.html",
styleUrls: ["login.component.css"]
})
export class LoginComponent {
animal: string;
name: string;
constructor(
private _formBuilder: FormBuilder,
iconRegistry: MatIconRegistry,
sanitizer: DomSanitizer,
public dialog: MatDialog
) {
iconRegistry.addSvgIcon(
"close",
sanitizer.bypassSecurityTrustResourceUrl(
"assets/icons/ic_close_48px.svg"
)
);
}
openDialog(): void {
let dialogRef = this.dialog.open(LoginDialogComponent, {
width: "400px",
data: { name: this.name, animal: this.animal }
});
dialogRef.afterClosed().subscribe(result => {
console.log("The dialog was closed");
this.animal = result;
});
}
}
#Component({
selector: "dialog-login",
templateUrl: "loginDialog.component.html",
styleUrls: ["loginDialog.component.css"]
})
export class LoginDialogComponent {
constructor(
private _formBuilder: FormBuilder,
public dialogRef: MatDialogRef<LoginDialogComponent>,
#Inject(MAT_DIALOG_DATA) public data: any
) {}
onNoClick(): void {
this.dialogRef.close();
}
ngOnInit() {
this.firstFormGroup = this._formBuilder.group({
firstCtrl: ["", Validators.required]
});
this.secondFormGroup = this._formBuilder.group({
secondCtrl: ["", Validators.required]
});
}
}
My Current Status:
My Goal:
There is no official fix yet. I have submitted a bug-report and it is being looked into. For now I have researched and found a workaround for this issue. I had to add (selectionChange)="cambiaStep($event)" as an attribute to my <mat-vertical-stepper> tag. Then I had to add a <ng-container> under all of my <mat-step> tags. In each corresponding <ng-container>, I had to set an attribute based on which position it had in the stepper order. In each <ng-container> I had to add *ngIf="stepIndex === 0" but the 0 was based on its order in the steps (0: first, 1: second, 2: third, etc.)
My stepper ended up having code as such:
<mat-vertical-stepper (selectionChange)="cambiaStep($event)">
<mat-step>
<ng-container *ngIf="stepIndex === 0">
</ng-container>
</mat-step>
<mat-step>
<ng-container *ngIf="stepIndex === 1">
</ng-container>
</mat-step>
<mat-step >
<ng-container *ngIf="stepIndex === 2">
</ng-container>
</mat-step>
</mat-vertical-stepper>
I also had to add the event function in my component's *.ts file.
export class LoginDialogComponent {
stepIndex: number = 0;
cambiaStep(e) {
this.stepIndex = e.selectedIndex;
}
constructor() {}
}
I just copy pasted your code in default angular-material stepper code and it's showing like your goal
https://stackblitz.com/edit/angular-tpeo6s?embed=1&file=app/stepper-overview-example.html
Edit
It seems angular material bug to me.
if stepper is put out of tabs, it is working but inside tab, though aria-expanded="false" for inactive steps , material is not adding style="height: 0px; visibility: hidden;" to hide inactive steps.
you can log issues related to angular material 2 HERE

Angular 2 Dynamic Template Directives does not work

I have a component which takes in a dynamic template which looks like this:
<ion-list>
<ion-item-sliding *ngFor="let entity of entityList" #item>
<ion-item (click)="navigateToDetail(entity.id)">
<template [ngTemplateOutlet]="template" [ngOutletContext]="{entity: entity}"></template>
</ion-item>
<ion-item-options side="right">
<button ion-button color="danger" *ngIf="config && config.canDelete" (click)="delete(entity.id)">
<ion-icon name="trash"></ion-icon>Delete
</button>
<button ion-button color="dark" >
<ion-icon name="more"></ion-icon>More
</button>
</ion-item-options>
</ion-item-sliding>
<ion-list-header>
<button *ngIf="config && config.canCreate" (click)="create()"
ion-button full color="secondary">
Create New<ion-icon name="add"></ion-icon>
</button>
</ion-list-header>
</ion-list>
and the typescript looks like so:
export class PageListBaseComponent<T extends IHasId> {
#Input() template: TemplateRef<any>;
#Input() detailPageType: any;
#Input() config: PageListConfiguration
#Input() set baseProvider(provider: ProviderBase<T>) {
provider.getList().subscribe(entities => {
this.entityList = entities;
console.log(entities);
});
}
public entityList: T[];
constructor(public navCtrl: NavController, public navParams: NavParams) {
console.log("ctor");
}
create() {
if (this.config && this.config.canCreate) {
//TODO: initialize entity
let entity = {}
this.navCtrl.push(this.detailPageType, { entity });
}
}
delete(id: number) {
console.log(id);
if(this.config && this.config.canDelete)
{
this.baseProvider.deleteById(id).subscribe(result => {
console.log(result);
});
}
}
navigateToDetail(id: number) {
this.navCtrl.push(this.detailPageType, { id })
}
}
And then I have a template that looks like so:
<template #myTemplate let-entity="entity">
<ion-item>
<ion-avatar item-left>
<img src="http://modexenergy.com/wp-content/themes/modex_wp/img/avatar.png">
</ion-avatar>
<h2>{{ entity.email }}</h2>
<ion-icon name="arrow-forward" item-right></ion-icon>
</ion-item>
</template>
My issue is the <ion-item> Right now I need to use it twice which I do not want to do, For some reason if i try and render the items dynamically they do not appear in the list, so I need to leave <ion-item> wrapping the template, that would be fine, except the directives don't respect there parent. Meaning if I use the item-left directive in a template, and the template does not include an <ion-item> my directives are ignored.
What can I do to fix this, if I can get away with out using both that would be nice, but if not is there a way render the first <ion-item> with no style?

Ionic2-array not updating on html side

I am new in Ionic2 and Angular2 trying to update my array at front side but its not updating.Moreover its updating perfectly at backend (ts),checked using console. need your help
My Component:
import { Component } from '#angular/core';
import { NavController, NavParams, ViewController } from 'ionic-angular';
#Component({
selector: 'page-modal-filter',
templateUrl: 'modal-filter.html'
})
export class ModalFilterPage {
public fil=[];
public BRANDNAME: any;
public srts:any;
constructor(public nav: NavController, public viewCtrl: ViewController, public navParams: NavParams) {
this.fil = [];
this.srts="ABCD";
if (navParams.get('tabName') == 'filter') {
let data = navParams.get('data');
data.map(d => {
for (let op in d.OPTIONGROUP) {
for (let x in d.OPTIONGROUP[op]) {
if (x != "UPC") {
if (!this.fil[x]) {
this.fil[x] = [];
}
if (this.fil[x].indexOf(d.OPTIONGROUP[op][x]) == -1) {
this.fil[x].push(d.OPTIONGROUP[op][x]);
}
}
}
}
})
console.log(this.fil);
}
}
closeModal() {
// this.nav.pop();
this.viewCtrl.dismiss(true);
}
}
"fil" array not showing on frontside of html but console show its perfectly.
My html code:
fil array not showing
<ion-header>
<ion-navbar color="primary">
<ion-buttons start>
<button ion-button (click)="closeModal()">
<ion-icon name="close"></ion-icon>
</button>
</ion-buttons>
<ion-title>Search Result(105)</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding class="tab-filter">
<!--filter list-->
<pre>{{fil}}</pre>
<pre>{{srts}}</pre>
<ion-list class="list-no-border">
<ion-item>
<ion-label> PLACE</ion-label>
<ion-select>
<ion-option value="">All Regions</ion-option>
<ion-option value="vn">Vietnam</ion-option>
</ion-select>
</ion-item>
<ion-item class="price-ranger">
<ion-label>Price</ion-label>
<ion-input type="text" placeholder="Min"></ion-input>
-
<ion-input type="text" placeholder="Max"></ion-input>
</ion-item>
<ion-item>
<ion-label>Free shipping</ion-label>
<ion-toggle checked="false"></ion-toggle>
</ion-item>
<ion-item>
<ion-label>Once pice only</ion-label>
<ion-toggle checked="false"></ion-toggle>
</ion-item>
<ion-item>
<ion-label>Sale items</ion-label>
<ion-toggle checked="false"></ion-toggle>
</ion-item>
</ion-list>
</ion-content>
<!--Footer buttons-->
<ion-footer class="category">
<ion-toolbar position="bottom">
<ion-buttons end>
<button ion-button (click)="closeModal()">
CANCEL
</button>
<button ion-button (click)="closeModal()">
<span ion-text color="gray">APPLY</span>
</button>
</ion-buttons>
</ion-toolbar>
</ion-footer>
Your {{fil}} is an array yet you are declaring it on the view as a simple property. Angular does not automatically interpret an array with string interpolation.
For arrays you need to use *ngFor
So if you want like you have stated is being displayed in your console.log you could write something like
<div *ngFor="let item of fil">
<ion-item *ngFor="let color of item.COLOR">
{{color.propertyName}}
<ion-item>
<ion-item *ngFor="let size of item.SIZE">
{{color.propertyName}}
<ion-item>
</div>
I resolved my issue by using
this.fil = [];
to
this.fil={}

Categories

Resources