ion-slides looping trick - not updating - ionic2

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>

Related

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

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 :)

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.

Foundation Reveal Modal and HTML5 history API manipulation

I am trying to solve an issue with modals. What I want to do is allow the user to click the browser's back button to dismiss a modal and return to the original state of the page, this is: without modal. For such purpose I thought about using HTML 5 history API.
I started trying to append a querystring parameter to the URL, such as http://...page.html?show_modal=[yes|no] but I ended leaving this approach because I couldn't handle all the stuff involving popstate event, pageshow event, etc. I couldn't make it work and it overwhelmed me.
Then I tried with a more simple approach involving a hash appended to the URL, such as http://...page.html#modal, and the hashchange event. This approach is working better for me and I almost have it.
When the user clicks the button to show the modal, he or she can click the browser's back button and it will dismiss the modal. Furthermore, after that, the user can click the browser's forward button and it will show the modal again. Very nice! The user can also navigate directly to the URL with the hash to access directly this state of the page, as well as he or she can bookmark such state of the page. It's working pretty neat and I'm rather happy with the results.
The problem is that it is not working totally perfect. When the user dismiss the modal by clicking the background, the ESC key or the X in the upper right corner, the history starts to mess up. Try it: open the modal by clicking on the button, then click the background to dismiss it (look a the URL in the address bar, first problem here is that the hash isn't removed), then click your browser back button and you will see it isn't working correctly. You will end with a duplicate in your history and you have to click the back button twice in order to go to the previous page. This is not desirable from an UX viewpoint. Does anyone know a solution to this?
I provide my code in this CodePen and at the end of this question. I suggest trying it in your own machine and NOT IN Codepen, so you can view the hash in the URL, etc. Also, it doesn't work in Codepen Full mode, I don't know why.
Thanks!!
I am using Foundation 5.2.1
HTML
<div class="row">
<div class="small-12 columns">
<h1>Reveal Modal</h1>
<h2>Manipulation of the browser history for a better UX</h2>
<a class="button radius" href="#" data-reveal-id="sampleModal" id="button">Show Modal...</a>
</div>
</div>
<!-- ############# -->
<!-- MODAL -->
<!-- ############# -->
<div id="sampleModal" class="reveal-modal medium" data-reveal>
<h2>Hi!</h2>
<p>You may think you are on a new page now, but you aren't. Try to click your browser <kbd>Back</kbd> button to dismiss this modal and return to the the page you were viewing.</p>
<a class="close-reveal-modal">×</a>
</div>
JavaScript
function setModalHash(url, present) {
var a = $('<a>', { href:url } )[0]; // http://tutorialzine.com/2013/07/quick-tip-parse-urls/
var newHash = "";
if (present === true) {
newHash = "#modal";
}
// Build the resulting URL
result = a.protocol + "//" + a.hostname + ":" + a.port + a.pathname + a.search + newHash;
return result;
}
$("#button").on('click', function() {
history.pushState(null, null, setModalHash(document.URL, true));
});
$(window).on("hashchange load",function(e) {
// Handling also the load event allows navigation directly to http://host/path/to/file#modal and bookmarking it
if (document.location.hash == "#modal") {
$("#sampleModal").foundation("reveal","open");
}
else {
$("#sampleModal").foundation("reveal","close");
}
});
I've been messing with the history api/History.js in combination with session storage to maintain modal state, and open/close based upon user navigation. I've finally achieved about 90% of my goal, but history is implemented very poorly in Safari and iOS Safari so remove the features for these browsers.
Some of the problems you may be running into with the hash approach is that when you use the # with pushstate it actually doesn't push a new object into the history state. It sometimes seems to push history onto the stack and you could use history.back() to fire a popstate, but if you were to say refresh the page with your hashurl and do some sort of check for hash on page initiation, there doesn't seem to be a new history pushed onto the stack, and therefore on backwards navigation the user will leave the site rather than closing the modal.
Here is my implementation working for all browsers except for where it falls back to normal behavior is Safari:
http://dtothefp.github.io/hosted_modal_history_sample/
https://github.com/dtothefp/html5history_express_modal_toggle
Like I said I use History.js in combination with sessionstorage because annoyingly enough, in the popstate for closing the modal the history object is removed, which is exactly when I would need it. In all a very poorly implemented API.
I don't change the URL because this project does not have a backend, so if I change the URL with no hash, on page refresh the page would not be found. An alternate implementation would be a query string, which will properly update history when used in the pushstate, but ends up being bad UX because if the user closes the modal not using the backwards navigation (i.e. hitting the cancel button or clicking off), removing the query string would result in a page refresh.

Zurb Foundation 5 accordion not pushing content below down

I am using Foundation 5 and trying to include a menu inside of an accordion. When the accordion is clicked and expands it works fine but rather than pushing the below content down when opened, it opens over the background of the below content, but under the content of the below content.
I have tried to change the z-index of the accordion to 0 but it does not help. I have also added the clearfix class to no avail.
Can be seen here
Any help or suggestions would be appreciated.
Thanks,
Pete
The error is in this line:
<div class="large-3 medium-4 columns hide-for-small sidebar-wrap" data-equalizer-watch="" style="height: 228px;">
You've set a fixed heigth for the container. Since it is already at max height, it can't expand further down.
remove style="height: 228px;" and everything gets pushed down. If you need a fixed height, so the content doesn't snap up and down everytime the user clicks on the accordion set it to height: 402px;. Thats the value Chrome tells me for 4 elements, with one expanded.

Hyperlink On x-axis

Please look at the jsfiddle
I am wanting to be able to click on home and about and for it to scroll to where the centre of where the href is located?
<a name="index">home</a>
<a name="about">about</a>
<div></div>
<div class="home"></div>
but even this bit of code isn't working. Why?
I want a navigation panel with Home, About, Contact and Info Horizontally placed. And I want that to be perfectly in the centre. and to be fixed position.
I have managed to do this by
$(window).scroll(function(){
$('.navigation').css({
'right': $(this).scrollLeft()
});
});
But it is not perfectly in the centre I then want when you click on one of these it navigates you to the corresponding part of the page which is on a horizontal line with the other pages.
This is what you need:
home
about
<a><div id="about"></div></a>
<a><div id="index" class="home"></div></a>
explanation: href="#index" uses # and that indicates you use an id.
Put an id with the same name in de div.. and you go to that place
You dont even need the <a> tags in de div