I will create a shopping app using ionic 2. In the products details I have created a stepper for increment and decrement value of quantity.
How can I get the input value within ionic 2 in my Component?
Solution:
1- app/pages/index.html
In Angular 2, you should use ngModel in the template.
<ion-header>
<ion-navbar primary>
</ion-navbar>
</ion-header>
<ion-content>
<ion-item>
<button lightgray full (click)="incrementQty()">+</button>
<ion-item>
<ion-input type="number" min="1" [value]="qty" [(ngModel)]="qty"></ion-input>
</ion-item>
<button lightgray full (click)="decrementQty()">-</button>
</ion-item>
</ion-content>
2- app/pages/index.ts
import { Component} from '#angular/core';
import { NavController, Slides} from 'ionic-angular';
#Component({
templateUrl: 'build/pages/titlepage/titlepage.html',
})
export class titlePage {
qty:any;
constructor(private nav: NavController) {
this.qty = 1;
}
// increment product qty
incrementQty() {
console.log(this.qty+1);
this.qty += 1;
}
// decrement product qty
decrementQty() {
if(this.qty-1 < 1 ){
this.qty = 1
console.log('1->'+this.qty);
}else{
this.qty -= 1;
console.log('2->'+this.qty);
}
}
}
Or as an alternative solution you may use the more appropriate Form controls designed for angular 2. (learn more here )
Example:
Typescript
import {Component, Input} from '#angular/core';
import {FORM_DIRECTIVES, FormBuilder, ControlGroup, AbstractControl} from '#angular/common';
import {IONIC_DIRECTIVES} from 'ionic-angular';
#Component({
selector: 'chat-form',
templateUrl: '/client/components/chat-form/chat-form.html',
directives: [IONIC_DIRECTIVES, FORM_DIRECTIVES],
pipes: [],
styleUrls: []
})
export class ChatFormComponent {
chatForm:ControlGroup;
messageInput:AbstractControl;
constructor(private translate:TranslateService, private formBuilder:FormBuilder) {
this.chatForm = formBuilder.group({messageInput: ['']})
this.messageInput = this.chatForm.controls['messageInput'];
}
sendMessage() {
console.log('sendMessage: ', this.messageInput.value);
}
}
Template
<form [ngFormModel]="chatForm" (ngSubmit)="sendMessage()">
<ion-input type="text" [ngFormControl]="messageInput" placeholder="{{'chat.form.placeholder' | translate }}"></ion-input>
<button fab>
<ion-icon name="send"></ion-icon>
</button>
</form>
Related
I am new to ionic4. Before that i try ionic3 in that menu is working proper.
But now i migrate to ionic4.
I just create new project with inbuild menu option. It run successfully in web browser But When I run on my Android mobile device , Menu open but after clicking it did not close.
I use:
Ionic version:5.2.3
Node version:v10.16.3
Cordova version:9.0.0
First attempt:
my app.component.html file:
<ion-app>
<ion-menu type="overlay"side="start" contentId="menu-content">
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-menu-toggle auto-hide="false" *ngFor="let p of appPages">
<ion-item [routerDirection]="'root'" [routerLink]="[p.url]" *ngFor="let p of appPages" (click)="togglemenu()">
<ion-icon slot="start" [name]="p.icon"></ion-icon>
<ion-label>
{{p.title}}
</ion-label>
</ion-item>
</ion-menu-toggle>
</ion-list>
</ion-content>
</ion-menu>
<ion-router-outlet main id="menu-content"></ion-router-outlet>
</ion-app>
my app.component.ts file:
import { Component } from '#angular/core';
import { Platform,MenuController } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
#Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.scss']
})
export class AppComponent {
public appPages = [
{
title: 'Home',
url: '/home',
icon: 'home'
},
{
title: 'List',
url: '/list',
icon: 'list'
}
];
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
public menu: MenuController,
private statusBar: StatusBar
) {
this.initializeApp();
}
initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}
togglemenu(){
this.menu.close();
console.log("clikc");
}
}
Second attempt:
<ion-app>
<ion-split-pane contentId="menu-content" side="start">
<ion-menu type="overlay">
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-menu-toggle auto-hide="false" *ngFor="let p of appPages">
<ion-item [routerDirection]="'root'" [routerLink]="[p.url]" *ngFor="let p of appPages">
<ion-icon slot="start" [name]="p.icon"></ion-icon>
<ion-label>
{{p.title}}
</ion-label>
</ion-item>
</ion-menu-toggle>
</ion-list>
</ion-content>
</ion-menu>
<ion-router-outlet main></ion-router-outlet>
</ion-split-pane>
</ion-app>
Looking at the ion-menu-toggle documentation it states:
"In case it's desired to keep ion-menu-toggle always visible, the autoHide property can be set to false."
https://ionicframework.com/docs/api/menu-toggle
It looks like you have this set to false. You can remove auto-hide="false" because it defaults to true.
Am new to angular and am starting off with a simple login form. However the form values are always showing up as empty - even if values have been entered before form submission.
I have created a login component which is imported in app module. The page comes up, but the submission does not carry any values. I have removed all Angular validation checks for debugging but the values received in my onsubmit function are still empty.
I have pasted the component code.Below.
login.component.html
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<div class="form-group" >
<div class="form-group">
<input type="email" class="form-control" formcontrolname="username"
placeholder="Email Id" required autofocus/><br/>
</div>
<div class="form-group">
<input type="password" class="form-control" formcontrolname="password" placeholder="Password" required/><br/>
</div>
<div class="form-group">
<button>Login</button>
<a href="/public/register" class="btn" >Register</a>
</div>
app.component
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
#NgModule({
imports: [ BrowserModule, AppRoutingModule, FormsModule,
ReactiveFormsModule ],
declarations: [ AppComponent, HelloComponent, LoginComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
login.component.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
submitted = false;
returnUrl = '';
constructor(
private formBuilder: FormBuilder,
private router: Router
) {
}
ngOnInit() {
this.loginForm = this.formBuilder.group ({
username: ['', Validators.required],
password: ['', Validators.required]
});
}
get user() { return this.loginForm.controls; }
onSubmit() {
// stop if form is invalid
/* if (this.loginForm.invalid) {
console.log("Returning");
return;
} */
this.submitted = true;
console.log('login values:');
console.log(this.user.username.value, this.user.password.value);
this.returnUrl='/home';
// this.router.navigate([this.returnUrl]);
}
}
You can try this:
get user() { return this.loginForm.value; }
Knew it would be something super silly and trivial - turned out to be a case sensitivity problem issue on my end. Changed 'formcontrolname' to 'formControlName' and it started working! Duh!
I am using Ionic 4, I want to do different menu content in different page. I have add menuId inside my code, but I only get the second page menu. My first page menu is missing.
I think you should build 1 menu and then just populate its page list depending on the page being visited.
So your code would look something like this:
import { Component, OnInit } from '#angular/core';
import { Router, RouterEvent } from '#angular/router';
#Component({
selector: 'app-menu',
templateUrl: './menu.page.html',
styleUrls: ['./menu.page.scss'],
})
export class MenuPage implements OnInit {
selectedPath = '';
pages = getPages();
constructor(private router: Router) {
this.router.events.subscribe((event: RouterEvent) => {
if (event && event.url) {
this.selectedPath = event.url;
}
});
}
getPages() : any[] {
if (this.router.url === '/page1') {
return [
{
title: 'First Page with Tabs',
url: '/menu/first'
},
{
title: 'Second Page blank',
url: '/menu/second'
}
];
}
if (this.router.url === '/page2') {
return [
{
title: 'First Page with Tabs',
url: '/menu/first'
},
{
title: 'Second Page blank',
url: '/menu/second'
}
];
}
}
ngOnInit() {
}
}
And then display it like this:
<ion-split-pane>
<ion-menu contentId="content">
<ion-header>
<ion-toolbar color="primary">
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-menu-toggle auto-hide="false" *ngFor="let p of pages">
<ion-item [routerLink]="p.url" routerDirection="root" [class.active-item]="selectedPath.startsWith(p.url)">
<ion-label>
{{ p.title }}
</ion-label>
</ion-item>
</ion-menu-toggle>
<ion-item tappable routerLink="/login" routerDirection="root">
<ion-icon name="log-out" slot="start"></ion-icon>
Logout
</ion-item>
</ion-list>
</ion-content>
</ion-menu>
<ion-router-outlet id="content" main></ion-router-outlet>
</ion-split-pane>
Full tutorial about setting up a menu like this is available here:
How to Combine Ionic 4 Tabs and Side Menu Navigation [v4] - Ionic AcademyIonic Academy
Although the code I used as an example above for get getPages() is the bit you would write yourself.
I've started working with angular5 and I'm trying to get the value of a select option and it's assigned ID onChange.
Component
import { Component, OnInit, EventEmitter } from '#angular/core';
// Services
import { LookupDataService } from '../../../service/lookup-data.service';
#Component({
selector: 'diversity-dropdown',
templateUrl: './diversity-dropdown.component.html',
providers: [LookupDataService]
})
export class DiversityDropdownComponent implements OnInit {
diversityForm: IDiversityForm[];
title = 'Lookup data';
selectedDiversity = '';
constructor(private readonly lookupDataService: LookupDataService) { }
ngOnInit() {
this.lookupDataService.getDiversityForm().subscribe((diversityForm: IDiversityForm[]) => {
this.diversityForm = diversityForm;
console.log(diversityForm);
}
);
}
onChange($event) {
console.log($event);
}
}
View
<div *ngFor='let section of diversityForm'>
<span class="label label-default">{{section.labelText}}</span>
<select (change)="onChange($event)" ng-model="">
<<option *ngFor='let dropdown of section.lookupDropdowns' id="{{dropdown.labelText}}" value="{{dropdown.value}} {{dropdown.labelText}}">{{dropdown.value}}</option>
</select>
<br />
</div>
Data
I've tried $event.target.id but in the console it's an empty string. $event.target.value works however.
Is there an easy way of doing what I am trying to do?
Stackblitz demo here
You should use select in this way:
HTML:
<select [(ngModel)]="newGovId.first_id_type" (change)="function($event)">
<option [ngValue]="null">Select something</option>
<option *ngFor="let option of options"
[ngValue]="option.value" [innerHtml]="option.text"></option>
</select>
The context of each option should be in the variable you're looping.
I created an input component to reuse it between a few forms. In one of then, it's working perfectly, but in the other, it's not.
It doesn't throw any erros. I even receive the input value after submit.
code.component.html
<div [ngClass]="aplicaCssErro(ag)">
<label for="code">Code</label>
<input id="code" name="code" type="text" class="form-control" [(ngModel)]="value" required #ag="ngModel"
maxlength="4" minlength="4" (blur)="formatCode(ag)">
<div *ngIf="verificaValidTouched(ag)" class="msgErroText">
<gce-campo-control-erro [mostrarErro]="ag?.errors?.required" msgErro="the code is required">
</gce-campo-control-erro>
</div>
code.component.ts
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'gce-input-code',
templateUrl: './input-code.component.html',
styleUrls: ['./input-code.component.scss']
})
export class InputCodeComponent implements OnInit {
#Input() value: string = "";
constructor() { }
ngOnInit() {
}
//some functions
}
form.component.html
The problem is that the form is not validating it, just the first input.
I think the form is not recognizing it as one of it's inputs.
<form (ngSubmit)="onSubmitForm2(f)" #f="ngForm">
<div class="row">
<div class="col-sm-6" [ngClass]="aplicaCssErro(apelido)">
<label for="apelido">Apelido da conta</label>
<input id="apelido" name="apelido" type="text" class="form-control" alt="Apelido" [(ngModel)]="conta.apelido" required #apelido="ngModel">
<div *ngIf="verificaValidTouched(apelido)" class="msgErroText">
<gce-campo-control-erro [mostrarErro]="apelido?.errors?.required" msgErro="O Apelido é obrigatório.">
</gce-campo-control-erro>
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<div class="col-sm-2">
<gce-input-code name="code" [(ngModel)]="user.code" #code="ngModel" ngDefaultControl></gce-input-code>
</div>
</div>
</div>
<div class="row">
<button class="btn btn-default" name="btn2" type="submit" alt="Continuar" [disabled]="!f.valid">Continue</button>
</div>
Any help?
If I understand your question correctly. You are trying to make it so the form(ngForm) can validate the custom component that wraps around the input(gce-input-code).
A normal form does not have any way to know what is going in/out of the component as it is Angular component. You would have to enhance your code.component.ts to include all the connectors (ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS) into it.
Checkout this blog
https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html#custom-form-control-considerations
and its plnkr(exerpt code below)
https://plnkr.co/edit/6xVdppNQoLcsXGMf7tph?p=info
import { Component, OnInit, forwardRef, Input, OnChanges } from '#angular/core';
import { FormControl, ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS }
from '#angular/forms';
export function createCounterRangeValidator(maxValue, minValue) {
return (c: FormControl) => {
let err = {
rangeError: {
given: c.value,
max: maxValue || 10,
min: minValue || 0
}
};
return (c.value > +maxValue || c.value < +minValue) ? err: null;
}
}
#Component({
selector: 'counter-input',
template: `
<button (click)="increase()">+</button> {{counterValue}} <button (click)="decrease()">-</button>
`,
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CounterInputComponent), multi: true },
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => CounterInputComponent), multi: true }
]
})
export class CounterInputComponent implements ControlValueAccessor, OnChanges {
propagateChange:any = () => {};
validateFn:any = () => {};
#Input('counterValue') _counterValue = 0;
#Input() counterRangeMax;
#Input() counterRangeMin;
get counterValue() {
return this._counterValue;
}
set counterValue(val) {
this._counterValue = val;
this.propagateChange(val);
}
ngOnChanges(inputs) {
if (inputs.counterRangeMax || inputs.counterRangeMin) {
this.validateFn = createCounterRangeValidator(this.counterRangeMax, this.counterRangeMin);
this.propagateChange(this.counterValue);
}
}
writeValue(value) {
if (value) {
this.counterValue = value;
}
}
registerOnChange(fn) {
this.propagateChange = fn;
}
registerOnTouched() {}
increase() {
this.counterValue++;
}
decrease() {
this.counterValue--;
}
validate(c: FormControl) {
return this.validateFn(c);
}
}