Ionic 3 ion-input captures focus of the whole row in Android - ionic2

This ionic page is just a form with some elements. In the Phone field, I have created a modal that opens when you click on an image:
<ion-grid>
<ion-row>
<ion-col>
<form #registerForm="ngForm" novalidate [formGroup]="form">
[...]
<ion-item>
<img item-left margin-left src={{flagPath}} (click)="presentCountryModal()">
<p item-left (click)="presentCountryModal()">+{{countryCode}}</p>
<ion-icon item-left name="arrow-dropdown" (click)="presentCountryModal()">
</ion-icon>
<ion-input
placeholder="Phone"
type="text"
[(ngModel)]="account.phone"
name="phone"
required
pattern=".{8,}"
#phone="ngModel"
></ion-input>
</ion-item>
It works perfectly on iOS and Windows on ionic-lab. But in Android the behavior is different: when I click on the image, the Phone ion-input gets the focus and the whole form moves up, making space for the keyboard and hiding the field under the header.
I'd like to:
1) Be able to make the image clickable.
2) Disable the automatic scrolling when an ion-input gets focused. I've tried keyboard.disableScroll(true) with no success.
Any ideas? Thanks!
UPDATE:
As explained here, adding .input-cover { position: static; } to the scss files stabilizes the form and makes the image click event responsive! So that solves the first question.
But I still have the problem that, when the keyboard opens, the whole page moves up and the top elements hide below the header (and you can't scroll them down).

1) You need to make a separated ion-item form the img. If you have an ion-input inside an ion-item, everything you put together will be "part" of that input.
2) The easiest way to do this without manipulating via ts is using a regular input, not the ion-input or using the ion-input inside a div instead of the ion-item. The second one i'm just guesing, since the behaviour of the scroll for showing the keyboard happens if you have an ion-input inside ion-item.
Hope this helps :)

Related

Ionic 2 select: remove selected option

I'm using ion-select component in a form, but got a problem: if users selects one option, but then wanna remove it, it doesn't give the option. I could add a <ion-option> with blank value, but think it wouldn't be nice. Is there a better way to solve that?
EDIT:
This is how my select options looks right now:
If the users selects one option and then changes his mind and don't wanna select any option, it doesn't seems pretty clear the way he can do that. Even if add a "Remove Option" with blank value, it still looks like an option, doesn't seems nice to me. With a traditional select, the blank option without a text seems pretty intuitive. But in this case, I was thinking in something like a " (X) Remove selected", near to "Cancelar/Confirmar" options in the footer, or something like that. Any ideas?
Ps: also, ion-option seems to strip any html tag I put on my option, so it keeps pretty tough to format my "select none" option
#sonu's solution will work if the user wants to click on the ion-select again and chose a select-nothing option, but I don't find that a pleasant experience.
An alternative way to get to what you want is to use a small clear button next to your ion-select, which appears only when user has already selected something:
<ion-label>Options</ion-label>
<ion-select [(ngModel)]="option">
<ion-option value="f">Female</ion-option>
<ion-option value="m">Male</ion-option>
</ion-select>
<div *ngIf="option=='m' || option=='f'">
<ion-label> {{option}} </ion-label>
<ion-button (click)='removeSelection()'>
<ion-icon name='close'></ion-icon>
</ion-button>
</div>
Where removeSelection() is a function that changes the selection to "No selection", perhaps by setting this.option=null.
Of course, you can style this button as you wish. You may also want to look at ionic chips. In particular, delete chips are one way to implement your intention.
To trigger a function that handles the cancel selection you can just use the ionCancel attribute like this
<ion-select okText="Select" cancelText="Clear"formControlName="selectionValue" (ionCancel)="clearSelection()">
<ion-option *ngFor="let selection of selections" [value]="selection.value">{{selection.description}}</ion-option>
</ion-select>
And in the code just implement the function you declared; in this case clearSelection()
clearSelection() {
this.myModel.selectedValue = null;
}
Now every time you press the clear button your function will be triggered
Documentation: ion-select
I had a slight different requirement - after selecting an option and clicking on OK button, the selected value should be used in function called by ionChange and then selected option in ion-select should get deselected. I tried various solutions mentioned in various sites but none worked. Even the working solution in plunker http://embed.plnkr.co/2KVqL2ecColaXgzAfxWI?p=preview where the ngModel value is set to null didn't work for me.
So I tried myself different things and one them did the trick. Below is the way that worked for me:-
In HTML I have used #languageSelect as template reference variable for ViewChild in ion-select
<ion-label>Select Language</ion-label>
<ion-select #languageSelect (ionChange)="langSelected($event)">
<ion-option *ngFor="let lang of languages" [value]="lang">{{lang}}</ion-option>
</ion-select>
And in ts file it is used as
#ViewChild('languageSelect') languageSelect: Select;
In langSelected() it is cleared after doing the needful.
langSelected(value) {
//used the value as required
...
...
this.languageSelect.setValue(''); // This is clearing the selected option in ion-select
}
It's better way to have option with blank value.You can use code as per ionic docs
example:
<ion-label>Gender</ion-label>
<ion-select [(ngModel)]="gender">
<ion-option value="">Select Gender</ion-option>
<ion-option value="f">Female</ion-option>
<ion-option value="m">Male</ion-option>
</ion-select>
Or you can add any event for selection clear.

ion-slides looping trick - not updating

I am trying to pull off a "trick" in ionic2 as follows:
- I have one slide set to loop.
- When the slide is swiped I increase or decrease a variable
- that variable will cause different data to display in the slide.
This way I can get the full UI experience of the slides component without hardcoding or pre-loading all the other slides.
For eg lets say you are viewing data by day, I want to be able to slide back and forth to look at data from previous days. Given the change I will just reload the relevant days data.
It ALMOST works except that the slider doesnt seem to refresh properly when looping.
Take a look this
http://plnkr.co/edit/VlxrNO7I6sqLGHsLdB9R?p=preview
<ion-slides loop="true" (ionSlidePrevEnd)="slideChanged(-1)" (ionSlideNextEnd)="slideChanged(1)">
<ion-slide>Slide{{newval}}
Test
</ion-slide>
</ion-slides>
</ion-content>
Controller
export class HomePage {
appName = 'Ionic App';
newval: number = 0;
constructor(public navController: NavController) { }
slideChanged(step: number) {
this.newval = this.newval + step;
}
}
If you swipe back and forth the text doesnt change. It should increase or decrease eg Slide 1, Slide 2 etc...
BUT do a few swipes and then instead of swiping just click down on the slide and move it a little and THEN the label does refresh to give you the correct value!
Its almost like because I am looping - all thats displayed is the original slide value and not the updated value, until I click somewhere on the slide causing it to refresh.
So bottom line I assume this is a bug?
Is there any way I can trigger this "refresh" behaviour programmatically?
Thanks
Hi change your code for home.page.html to:
<ion-slides loop="true" (ionSlidePrevEnd)="slideChanged(-1)" (ionSlideNextEnd)="slideChanged(1)">
<ion-slide *ngFor="let item of items">Slide {{newval}}
<ion-list>
{{item}}
</ion-list>
</ion-slide>
</ion-slides>
I have tested it in plunker and the content will change when you slide. Do ngFor for each ion-slide instead of within the ion-slide
Try this ionic 3
<ion-slides loop="true" autoplay="1" speed="6000">
<ion-slide>Slide A</ion-slide>
<ion-slide>Slide B</ion-slide>
<ion-slide>Slide C</ion-slide>
</ion-slides>

make text in ion-select clickable

The template:
<ion-item>
<ion-label stacked>Select clickable option texts</ion-label>
<ion-select>
<ion-option value="opt1"><a (click)="myDetails()">Option one description<a> text</ion-option>
</ion-select>
</ion-item>
As you can see above, I want to make certain parts of the text in clickable, like to show the definition. I am using toast to show the text. But I am unable to get my head around making part of the text actually clickable.
Is there a way?

How to make Scrollable List area in a specific div in body (Onsen-UI)

I am making phonegap application using Onsen-UI. In that,I made a signup page. Now whenever I am trying to scroll the screen, whole body of page is scrolling. I want a particular division in a body that should scroll only. I have app Logo above the signup page and Logo is in the body part. So that shouldn't be scrolled. Only List div should be scrolled.
You can try using the <ons-scroller> directive:
<ons-scroller style="height: 200px">
<p>I am scrollable</p>
</ons-scroller>
I made a simple example: http://codepen.io/argelius/pen/dPeKOB
This option works to me:
<ons-page>
Toolbar here
<div class="background"></div>
<div class="content">
Scrollable content here
</div>
Fixed content here
</ons-page>
from: https://onsen.io/v2/api/js/ons-page.html

Unit test collapse behaviour of a div element in Angular-JS

I have a simple form that I want to be shown on a button click. i.e a button says "Add new User", then a the page expands and a form is shown, after the user finishes work with the form the form collapse back and a message is shown to the user.
The first problem i am facing is:
using this code
function AngularUI($scope, $window) {
$scope.collapse = function (selector) {
angular.element(selector).collapse();
}
}
and
<div class="ang-ui-test">
<button ng-click="collapse('#collapsible')">
using angular.element
</button>
<div id="collapsible" class="collapse">
some thing in here ...... !
</div>
<button type="button" class="btn btn-danger" data-toggle="collapse" data-target="#demo">
simple collapsible
</button>
<div id="demo" class="collapse in">This one work properly</div>
</div>
the second one that does not uses angular.element.collapse works properly.
The second problem is : how do I test the behavior mentioned above.
on the first button press, the one that uses angular.element if the div is hidden it is shown but, it does not hide the collapsible after it is shown.
( i.e a button says "Add new User", then a the page expands and a form is shown, after the user finishes work with the form the form collapse back and a message is shown to the user.
thanks in advance.
You're doing it wrong. It's bad juju to do DOM manipulations in the controller because you are trying to look for / manipulate the DOM before it had a chance to render/refresh/update. Think of all the JS in the controller being executed in it's own phase, and THEN all the HTML is updated to reflect the final model state.
Try using ng-class="{collapse:someBoolExpression}"
You could also take a look at ui-hide, ui-show and ui-toggle (from AngularUI, but I think we should probably add a ticket to let you customize the class used.
Try to get the mindset of doing DOM manipulation manually out of your head. It takes a while, but once you get used to it your development speed picks up exponentially. When you finally hit a wall where Angular can't already do the job for you, start reading up on directives and checkout AngularUI's source code for some good, commented examples.