ion-tabs and ion-content overlaps ion-header when i load an image in the header, it only happens the first time i'm visiting the page, after that it loads well.
this is the component
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
#Component({
selector: 'page-home',
templateUrl: 'app/home.page.html'
})
export class HomePage {
public image: string;
appName = 'Ionic App';
constructor(public navController: NavController) { }
ionViewDidLoad(){
this.image = "https://source.unsplash.com/640x300/?technology"
}
}
Here is the html
<ion-header>
<ion-navbar>
<ion-title></ion-title>
</ion-navbar>
<img class="cabecera" [src]="image" width="100%">
</ion-header>
<ion-content padding class="contenido">
Welcome to this <ion-icon name="ionic"></ion-icon> <b>Ionic 2 app</b>.
</ion-content>
Its posible to view an example in this plunker
https://plnkr.co/edit/CpBXmn?p=preview
The problem is that you are only loading the image (in the ionViewDidLoad function) after the rest of the content is loaded. After loading the image you need to resize the content, as described in this issue.
Add ViewChild and Content to your imports from #angular/core and ionic-angular, respectively:
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
Use #ViewChild to select the class for the ion-content component:
// ...
export class HomePage {
#ViewChild(Content) content: Content;
// ...
Then, once the image is loaded, call the resize method on content:
this.content.resize();
Related
In my Ionic 3 project I've implemented a simple list like this:
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
#Component({
selector: 'page-dossiers',
templateUrl: 'dossiers.html'
})
export class DossiersPage {
public heroes;
constructor(public navCtrl: NavController) {
this.heroes = [
{id: 1, name:'Superman'},
{id: 2, name:'Batman'},
{id: 5, name:'BatGirl'},
{id: 3, name:'Robin'},
{id: 4, name:'Flash'}
];
}
}
And than in the HTML:
<ion-content>
<ion-list>
<button ion-item *ngFor="let hero of heroes">
{{ hero.name }}
</button>
</ion-list>
</ion-content>
Now I've a problem with the rendering of the list, because the color of the label of each item is white and I don't see anything.
How I can solve this issue?
This is the result:
this is how the items are displayed
this is what I see if I touch the item
PS: Sorry for my bad english.
Have you edited the .scss file inside the page folder?
if not try adding a color="primary" or color="secondary" to your button tag.
I am trying to push new pages inside the current page's <div> element. I have tried various methods found on SO but nothing worked for me. I have this code right now which doesn't work.
<ion-content padding>
<div #pageView>
</div>
</ion-content>
import { Component, ViewChild } from '#angular/core';
import { IonicPage, NavController, NavParams, PopoverController } from 'ionic-angular';
export class Vehiclemaintenance {
#ViewChild('pageView') nav: NavController
Constructor(public navCtrl: NavController){}
loadPage(){
this.nav.push(myComponent)
}
}
This causes an error
ERROR TypeError: _this.nav.push is not a function
Where am I going wrong!
* Update that worked *
Instead of using a <div> element I used <ion-nav>
I'm Trying to call an API with ionic2, The data provider looks like this.the service returns an array of object.when i serve the app, the data is not displaying in the HTML template. How i can fix that issue.
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class VideoService {
videos: any;
constructor(public http: Http) {
console.log('Hello videoService Provider');
}
getVideos(){
this.http.get('http://mizikjams-lorisson.rhcloud.com/api/videos.json')
.map(res => res.json()).subscribe(data => {
this.videos= data.videos;
console.log(this.videos);
});
}
}
here's the html template code
<ion-content class=" mainpage card-background-page ">
<ion-list>
<ion-item *ngFor="let video of videos">
<ion-avatar item-left>
<img src="{{video.image}}">
</ion-avatar>
<h2>{{video.title}}</h2>
</ion-item>
</ion-list>
<div class="floatingbtn">
<ion-fab bottom right edge >
<button ion-fab color="orange" (click)="search();"><ion-icon name="search"></ion-icon></button>
</ion-fab>
</div>
</ion-content>
see working plunker - http://plnkr.co/edit/JtLm3K?p=preview
make sure you add the provider to the app.module
#NgModule({
imports: [ IonicModule.forRoot(AppComponent) ],
declarations: [ AppComponent, HomePage ],
entryComponents: [ HomePage ],
bootstrap: [ IonicApp ],
providers: [VideoService]
})
export class AppModule { }
provider
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class VideoService {
videos: any;
constructor(public http: Http) {
console.log('Hello videoService Provider');
}
getVideos(){
return this.http.get('http://mizikjams-lorisson.rhcloud.com/api/videos.json')
.map(res => res.json());
}
}
page1.ts
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { VideoService } from './videoService'
#Component({
selector: 'page-home',
templateUrl: 'app/home.page.html'
})
export class HomePage {
appName = 'Ionic App';
videos:any
constructor(public navController: NavController, public vs : VideoService) {
this.videos = this.vs.getVideos()
}
}
html
<ion-header>
<ion-navbar>
<ion-title>{{ appName }}</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-list>
<ion-item *ngFor="let video of (videos | async)?.videos ">
<ion-avatar item-left>
<img src="{{video.image}}">
</ion-avatar>
<h2>{{video.title}}</h2>
</ion-item>
</ion-list>
</ion-content>
I created a page with 3 tabs using ionic 2.Inside one page I created one button and on click of that button I navigate to a new child page by executing
the push command but whenever I am clicking the tab containing the child page I am not able to see the root page instead I see the new child page.
I want to see the root page on revisit of the tab page.
Below is my code.. here you can check in about.html i have placed one button to navigate to a child page.Navigation is happening but once I navigate then I am not able to see the about tab page without clicking on back button
tabs.html
<ion-tabs>
<ion-tab [root]="tab1Root" tabTitle="Home" tabIcon="home"></ion-tab>
<ion-tab [root]="tab2Root" tabTitle="About" tabIcon="information-circle"></ion-tab>
<ion-tab [root]="tab3Root" tabTitle="Contact" tabIcon="contacts"></ion-tab>
</ion-tabs>
tabs.ts
import { Component } from '#angular/core';
import { HomePage } from '../home/home';
import { AboutPage } from '../about/about';
import { ContactPage } from '../contact/contact';
#Component({
templateUrl: 'tabs.html'
})
export class TabsPage {
// this tells the tabs component which Pages
// should be each tab's root Page
tab1Root: any = HomePage;
tab2Root: any = AboutPage;
tab3Root: any = ContactPage;
constructor() {
}
}
abuot.html
<ion-header>
<ion-navbar>
<ion-title>
About
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<button ion-button (click)="navigate()" ion-button color="secondary">GO to LIst</button>
<!-- <button [navPush]="listPage" ion-button color="secondary">Go To About</button> -->
<!-- <button ion-button color="secondary">Secondary</button> -->
</ion-content>
about.ts
import { Component } from '#angular/core';
import {ListPage} from '../list/list';
import {ViewController, NavController} from 'ionic-angular';
#Component({
selector: 'page-about',
templateUrl: 'about.html'
})
export class AboutPage {
constructor(public navCtrl: NavController,public viewctr: ViewController) {
}
navigate(){
this.navCtrl.push(ListPage);
}
}
Just a stab in the dark since we cannot see any of your code (which should be an addition to any question on here). You could try using .setRoot() to get to the root page you're wanting.
import { NavController } from 'ionic-angular';
import { NameOfPage } from '../NameOfPage';
pageYouWant: any = NameOfPage;
constructor(public navctrl: NavController){}
onClickFunction(){
this.navCtrl.setRoot(pageYouWant)
}
I am trying ionic2 beta9 and am trying to create a custom component with ion-slide, but I am getting an error.
Parent Component
<ion-content class="home" padding>
<ion-slides loop="true">
<slide-item *ngFor="let image of [1,2,3,4,5]" [imgIdx]="image"></slide-item>
</ion-slides>
</ion-content>
slide-item Custom Component
<ion-slide>
<div class="bcontent">
<div class="bimg">
<img data-src="images/slide{{imgIdx}}.jpeg">
</div>
<p class="info">My text</p>
</div>
</ion-slide>
slide-item.ts
#Component({
selector: 'slide-item',
templateUrl: 'build/components/slide-item/slide-item.html',
directives: [Slides, Slide]
})
export class SlideItem {
#Input()
imgIdx: number;
constructor() {
console.log("SlideItem::constructor...imgIdx="+this.imgIdx);
}
}
I am getting the following error:
zone.js:461
Unhandled Promise rejection: Template parse errors:
No provider for Slides ("
for more info on Angular 2 Components.
-->
[ERROR ->]<ion-slide>
<div class="bcontent">
<div class="bimg">
"): SlideItem#6:0
; Zone: angular ; Task: Promise.then ; Value:
BaseException {message: "Template parse errors:↵No provider for Slides ("↵ …↵ <div class="bimg">↵"):
SlideItem#6:0", stack: "Error: Template parse errors:↵No provider for Slid…ndroid_asset/www/build/js/app.bundle.js:30622:41)"}message:
"Template parse errors:↵No provider for Slides ("↵ for more info on Angular 2 Components.↵-->↵[ERROR ->]<ion-slide>↵ <div class="bcontent">↵ <div class="bimg">↵"): SlideItem#6:0"
stack: "Error: Template parse errors:↵No provider for Slides ("↵ for more info on Angular 2 Components.↵-->↵[ERROR ->]<ion-slide>↵ <div class="bcontent">↵ <div class="bimg">↵"): SlideItem#6:0↵ at new BaseException (file:///android_asset/www/build/js/app.bundle.js:1760:23)↵ at TemplateParser.parse (file:///android_asset/www/build/js/app.bundle.js:16401:19)↵ at file:///android_asset/www/build/js/app.bundle.js:14643:64↵ at ZoneDelegate.invoke (file:///android_asset/www/build/js/zone.js:323:29)↵ at Object.onInvoke (file:///android_asset/www/build/js/app.bundle.js:30631:41)↵ at ZoneDelegate.invoke (file:///android_asset/www/build/js/zone.js:322:35)↵ at Zone.run (file:///android_asset/www/build/js/zone.js:216:44)↵ at file:///android_asset/www/build/js/zone.js:571:58↵ at ZoneDelegate.invokeTask (file:///android_asset/www/build/js/zone.js:356:38)↵ at Object.onInvokeTask (file:///android_asset/www/build/js/app.bundle.js:30622:41)"__proto__: ErrorconsoleError # zone.js:461_loop_1 # zone.js:490drainMicroTaskQueue # zone.js:494ZoneTask.invoke # zone.js:426
Why it doesn't work
I don't think it is possible with the current design of the Slide and Slides components. An ion-slide must be a child of an ion-slides element and it must be able to find its parent Slides within the same template.
Here's the source:
#Component({
selector: 'ion-slide',
template: '<div class="slide-zoom"><ng-content></ng-content></div>',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class Slide {
ele: HTMLElement;
#Input() zoom: any;
constructor(
elementRef: ElementRef,
#Host() public slides: Slides
) {
this.ele = elementRef.nativeElement;
this.ele.classList.add('swiper-slide');
slides.rapidUpdate();
}
ngOnDestroy() {
this.slides.rapidUpdate();
}
}
You can see that the parent Slides is required so that a Slide can trigger the Slides to update when one is dynamically added or destroyed. It is restricted to the current template with the #Host decorator.
You get a template error when you try to use ion-slide in your custom template because there is no Slides object within the template to be passed to the Slide.
One Partial-Solution
I played around with this and you can get it to work like this:
Remove the reference slides to the parent Slides object, sacrificing the ability to automatically update the Slides when you dynamically add/remove slides
Add the "slide-zoom" class to your custom slide.
The modified source for slides.ts:
#Component({
selector: 'ion-slide',
template: '<div class="slide-zoom"><ng-content></ng-content></div>',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class Slide {
ele: HTMLElement;
#Input() zoom: any;
constructor(
elementRef: ElementRef
) {
this.ele = elementRef.nativeElement;
this.ele.classList.add('swiper-slide');
}
}
And your slide item:
#Component({
selector: 'slide-item',
templateUrl: 'slide-item.html',
})
export class SlideItem {
#Input()
imgIdx: number;
constructor(elementRef: ElementRef) {
console.log("SlideItem::constructor...imgIdx="+this.imgIdx);
elementRef.nativeElement.classList.add('swiper-slide');
}
}
I say that this is a partial solution because you have to modify the ionic source and because now you have to manually call update the Slides update when you add/remove slides.
I did make some progress further modifying the ionic source to maintain the automatic update on add/remove slides including custom slide containers such as yours. But it just wasn't looking worth it compared to the option(s) below.
Partial Solution 2
The code for a Slide is really quite simple. You're best bet is probably just to define your own component directly (rather than wrapping ion-slide):
#Component({
selector: 'slide-item',
templateURL: 'slite-item.html',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class SlideItem {
ele: HTMLElement;
#Input() zoom: any;
#Input() imgIdx: number;
constructor(
elementRef: ElementRef
) {
this.ele = elementRef.nativeElement;
this.ele.classList.add('swiper-slide');
console.log("SlideItem::constructor...imgIdx="+this.imgIdx)
}
}
and template
<div class="slide-zoom bcontent">
<div class="bimg">
<img data-src="images/slide{{imgIdx}}.jpeg">
</div>
<p class="info">My text</p>
</div>
I'm calling this one a partial solution also because you have to maintain some extra source that mirrors Ionic. If the ionic slides implementation changes, you may have to update your custom slide.
Improved Solution
Here is a SO answer about extending a component. I haven't gotten this to work because as of now it isn't up to date with Angular (ComponentMetaData no longer exists), but I think it is a nicer approach. You will use this decorator to import and extend the Slide component.
export function CustomComponent(annotation: any) {
return function (target: Function) {
var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);
var parentAnnotation = parentAnnotations[0];
Object.keys(parentAnnotation).forEach(key => {
if (isPresent(parentAnnotation[key])) {
annotation[key] = parentAnnotation[key];
}
});
var metadata = new ComponentMetadata(annotation);
Reflect.defineMetadata('annotations', [ metadata ], target);
}
}
Your template will be the same as the previous solution, but the class is simplified to something like the following.
import { Slide } from 'ionic-angular';
#CustomComponent({
selector: 'slide-item',
templateURL: 'slite-item.html'
})
export class SlideItem extends Slide {
#Input() imgIdx: number;
}