mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
overhaul ion-views
This commit is contained in:
@@ -25,7 +25,6 @@ ion-app {
|
||||
}
|
||||
|
||||
ion-nav {
|
||||
// container of header.toolbar-container, footer.toolbar-container and .nav-item-container
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
@@ -33,75 +32,49 @@ ion-nav {
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.toolbar-container {
|
||||
// container of many toolbars for each view in the ion-nav
|
||||
position: relative;
|
||||
ion-view {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
// by default this is display: none;
|
||||
// and the transition animation will display it
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
|
||||
&.show-view {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
ion-toolbar {
|
||||
display: flex;
|
||||
min-height: 4.4rem;
|
||||
order: $flex-order-toolbar-top;
|
||||
}
|
||||
|
||||
footer.toolbar-container {
|
||||
.stage-off {
|
||||
transform: translateX(9999px);
|
||||
}
|
||||
|
||||
ion-toolbar[footer] {
|
||||
order: $flex-order-toolbar-bottom;
|
||||
}
|
||||
|
||||
ion-toolbar {
|
||||
// one view's toolbar, sibling to many view toolbars inside of .toolbar-container
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.nav-item-container {
|
||||
// container of many .nav-item's, each one containing one view
|
||||
position: relative;
|
||||
flex: 1;
|
||||
order: $flex-order-view-content;
|
||||
}
|
||||
|
||||
.tab-item-container {
|
||||
// container of each content for each tab component within a tabs component
|
||||
position: relative;
|
||||
flex: 1;
|
||||
order: $flex-order-view-content;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
// user created view, sibling to many .nav-item's, contained by .nav-item-container
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
// by default .nav-item is hidden
|
||||
// and the transition animation will display it
|
||||
display: none;
|
||||
|
||||
&.show-nav-item {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
ion-content {
|
||||
// content within the user created view, contained by .nav-item
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
display: block;
|
||||
flex: 1;
|
||||
order: $flex-order-view-content;
|
||||
}
|
||||
|
||||
.scroll-content {
|
||||
// extra div to allow overflow scrolling
|
||||
// extra div added by ion-content directive to allow for overflow scrolling
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
||||
@@ -265,15 +265,15 @@ export class NavBase {
|
||||
|
||||
cleanup() {
|
||||
this.items.forEach((item) => {
|
||||
|
||||
if (item && item.shouldDestroy) {
|
||||
this.remove(item);
|
||||
|
||||
util.dom.raf(() => {
|
||||
if (item) {
|
||||
if (item.shouldDestroy) {
|
||||
this.remove(item);
|
||||
item.destroy();
|
||||
});
|
||||
}
|
||||
|
||||
} else if(item.state !== ACTIVE_STATE) {
|
||||
item.cache();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@ import {bind} from 'angular2/di';
|
||||
|
||||
import * as util from 'ionic/util';
|
||||
import {NavController} from './nav-controller';
|
||||
import {NavView} from './nav-view';
|
||||
|
||||
const SHOW_VIEW_CSS = 'show-view';
|
||||
|
||||
|
||||
export class NavItem {
|
||||
@@ -15,7 +18,6 @@ export class NavItem {
|
||||
this.headerProtos = [];
|
||||
this.toolbarViews = [];
|
||||
this._titleEle = undefined;
|
||||
this.disposals = [];
|
||||
|
||||
// if it's possible to go back from this nav item
|
||||
this.enableBack = false;
|
||||
@@ -25,13 +27,19 @@ export class NavItem {
|
||||
// update if it's possible to go back from this nav item
|
||||
this.enableBack = !!this.nav.getPrevious(this);
|
||||
|
||||
if (!this.created) {
|
||||
return this.create();
|
||||
}
|
||||
return Promise.resolve();
|
||||
return this.create().then(() => {
|
||||
return new Promise(resolve => {
|
||||
this.viewEle && this.viewEle.classList.add(SHOW_VIEW_CSS);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
create() {
|
||||
if (this.created) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
this.created = true;
|
||||
|
||||
let resolve;
|
||||
@@ -43,30 +51,16 @@ export class NavItem {
|
||||
bind(NavItem).toValue(this)
|
||||
]);
|
||||
|
||||
this.nav.loader.loadNextToExistingLocation(this.Component, this.nav.contentElementRef, injector).then((componentRef) => {
|
||||
this.nav.loader.loadNextToExistingLocation(this.Component, this.nav.viewElementRef, injector).then((componentRef) => {
|
||||
|
||||
// content
|
||||
this.component = componentRef;
|
||||
|
||||
this.contentEle = componentRef.location.domElement;
|
||||
this.contentEle.classList.add('nav-item');
|
||||
this.contentEle.setAttribute('id', 'nav-item-' + this.id);
|
||||
this.viewEle = componentRef.location.domElement;
|
||||
this.viewEle.setAttribute('id', 'view-' + this.id);
|
||||
|
||||
if (componentRef && componentRef._dispose) {
|
||||
this.disposals.push(componentRef._dispose);
|
||||
}
|
||||
|
||||
|
||||
// TODO: talk to misko about correct way to set context
|
||||
let context = {
|
||||
boundElementIndex: 0,
|
||||
parentView: {
|
||||
_view: componentRef.location.parentView._view.componentChildViews[0]
|
||||
}
|
||||
};
|
||||
|
||||
for (let i = 0; i < this.headerProtos.length; i++) {
|
||||
this.createHeader(this.headerProtos[i], context, injector);
|
||||
if (componentRef && componentRef.dispose) {
|
||||
this._dispose = componentRef.dispose;
|
||||
}
|
||||
|
||||
resolve();
|
||||
@@ -75,44 +69,21 @@ export class NavItem {
|
||||
return promise;
|
||||
}
|
||||
|
||||
createHeader(toolbarProtoView, context, injector) {
|
||||
let headerContainer = this.nav.headerContainerRef;
|
||||
|
||||
if (!headerContainer) return;
|
||||
|
||||
let atIndex = -1;
|
||||
|
||||
let headerView = headerContainer.create(toolbarProtoView, atIndex, context, injector);
|
||||
|
||||
if (headerView) {
|
||||
this.toolbarViews.push(headerView);
|
||||
|
||||
this.disposals.push(() => {
|
||||
headerContainer.remove( headerContainer.indexOf(headerView) );
|
||||
});
|
||||
}
|
||||
viewElement() {
|
||||
return this.viewEle;
|
||||
}
|
||||
|
||||
addHeader(toolbarProtoView) {
|
||||
this.headerProtos.push(toolbarProtoView);
|
||||
contentElement() {
|
||||
return this.viewEle.querySelector('ion-content');
|
||||
}
|
||||
|
||||
getContent() {
|
||||
return this.contentEle;
|
||||
toolbarElements() {
|
||||
return this.viewEle.querySelectorAll('ion-toolbar');
|
||||
}
|
||||
|
||||
getToolbars() {
|
||||
let elements = [];
|
||||
for (let i = 0; i < this.toolbarViews.length; i++) {
|
||||
var toolbarView = this.toolbarViews[i];
|
||||
elements.push(toolbarView._view.render._view.rootNodes[0]);
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
getTitle() {
|
||||
titleElement() {
|
||||
if (this._titleEle === undefined) {
|
||||
let toolbarElements = this.getToolbars();
|
||||
let toolbarElements = this.toolbarElements();
|
||||
for (let i = 0; i < toolbarElements.length; i++) {
|
||||
var titleEle = toolbarElements[i].querySelector('ion-title');
|
||||
if (titleEle) {
|
||||
@@ -125,9 +96,9 @@ export class NavItem {
|
||||
return this._titleEle;
|
||||
}
|
||||
|
||||
getBackButton() {
|
||||
backButtonElement() {
|
||||
if (this._backBtn === undefined) {
|
||||
let toolbarElements = this.getToolbars();
|
||||
let toolbarElements = this.toolbarElements();
|
||||
for (let i = 0; i < toolbarElements.length; i++) {
|
||||
var backBtn = toolbarElements[i].querySelector('back-button');
|
||||
if (backBtn) {
|
||||
@@ -140,10 +111,12 @@ export class NavItem {
|
||||
return this._backBtn;
|
||||
}
|
||||
|
||||
cache() {
|
||||
this.viewEle.classList.remove(SHOW_VIEW_CSS);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
for (let i = 0; i < this.disposals.length; i++) {
|
||||
this.disposals[i]();
|
||||
}
|
||||
this._dispose && this._dispose();
|
||||
|
||||
// just to help prevent any possible memory leaks
|
||||
for (let name in this) {
|
||||
|
||||
@@ -17,15 +17,8 @@ import {ToolbarContainer} from '../toolbar/toolbar-container';
|
||||
}
|
||||
})
|
||||
@View({
|
||||
template: `
|
||||
<header class="toolbar-container">
|
||||
<template header-anchor></template>
|
||||
</header>
|
||||
<section class="nav-item-container">
|
||||
<template content-anchor></template>
|
||||
</section>
|
||||
`,
|
||||
directives: [HeaderAnchor, ContentAnchor, ToolbarContainer]
|
||||
template: `<template view-anchor></template>`,
|
||||
directives: [ViewAnchor]
|
||||
})
|
||||
export class Nav extends NavBase {
|
||||
constructor(elementRef: ElementRef, loader: DynamicComponentLoader, injector: Injector) {
|
||||
@@ -40,20 +33,10 @@ export class Nav extends NavBase {
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: '[header-anchor]'
|
||||
selector: '[view-anchor]'
|
||||
})
|
||||
class HeaderAnchor {
|
||||
constructor(@Ancestor() nav: Nav, viewContainerRef: ViewContainerRef) {
|
||||
nav.headerContainerRef = viewContainerRef;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: '[content-anchor]'
|
||||
})
|
||||
class ContentAnchor {
|
||||
class ViewAnchor {
|
||||
constructor(@Ancestor() nav: Nav, elementRef: ElementRef) {
|
||||
nav.contentElementRef = elementRef;
|
||||
nav.viewElementRef = elementRef;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
<ion-toolbar *header><ion-title>First Page: {{ val }}</ion-title></ion-toolbar>
|
||||
|
||||
<ion-toolbar><ion-title>First Page: {{ val }}</ion-title></ion-toolbar>
|
||||
|
||||
<ion-content class="padding">
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
|
||||
import {View} from 'angular2/src/core/annotations_impl/view';
|
||||
|
||||
import {NavController, HeaderTemplate, Toolbar, Content} from 'ionic/ionic';
|
||||
import {NavController, Toolbar, Content} from 'ionic/ionic';
|
||||
import {SecondPage} from './second-page';
|
||||
|
||||
|
||||
@Component({selector: 'ion-view'})
|
||||
@View({
|
||||
templateUrl: 'pages/first-page.html',
|
||||
directives: [HeaderTemplate, Toolbar, Content]
|
||||
directives: [Toolbar, Content]
|
||||
})
|
||||
export class FirstPage {
|
||||
constructor(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
<ion-toolbar *header><ion-title>Second Page</ion-title></ion-toolbar>
|
||||
<ion-toolbar><ion-title>Second Page</ion-title></ion-toolbar>
|
||||
|
||||
|
||||
<ion-content class="padding">
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
|
||||
import {View} from 'angular2/src/core/annotations_impl/view';
|
||||
|
||||
import {NavController, NavParams, HeaderTemplate, Toolbar, Content} from 'ionic/ionic';
|
||||
import {NavController, NavParams, Toolbar, Content} from 'ionic/ionic';
|
||||
import {ThirdPage} from './third-page';
|
||||
|
||||
|
||||
@Component()
|
||||
@Component({selector: 'ion-view'})
|
||||
@View({
|
||||
templateUrl: 'pages/second-page.html',
|
||||
directives: [HeaderTemplate, Toolbar, Content]
|
||||
directives: [Toolbar, Content]
|
||||
})
|
||||
export class SecondPage {
|
||||
constructor(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
<ion-toolbar *header><ion-title>Third Page</ion-title></ion-toolbar>
|
||||
<ion-toolbar><ion-title>Third Page</ion-title></ion-toolbar>
|
||||
|
||||
|
||||
<ion-content class="padding">
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
|
||||
import {View} from 'angular2/src/core/annotations_impl/view';
|
||||
|
||||
import {NavController, HeaderTemplate, Toolbar, Content} from 'ionic/ionic';
|
||||
import {NavController, Toolbar, Content} from 'ionic/ionic';
|
||||
|
||||
|
||||
@Component()
|
||||
@Component({selector: 'ion-view'})
|
||||
@View({
|
||||
templateUrl: 'pages/third-page.html',
|
||||
directives: [HeaderTemplate, Toolbar, Content]
|
||||
directives: [Toolbar, Content]
|
||||
})
|
||||
export class ThirdPage {
|
||||
constructor(
|
||||
|
||||
@@ -34,7 +34,6 @@ import {BackButton} from './back-button';
|
||||
})
|
||||
export class Toolbar {
|
||||
constructor(navItem: NavItem, elementRef: ElementRef) {
|
||||
|
||||
this.navItem = navItem;
|
||||
this.domElement = elementRef.domElement;
|
||||
this.config = Toolbar.config.invoke(this);
|
||||
@@ -95,18 +94,3 @@ export class Toolbar {
|
||||
|
||||
}
|
||||
new IonicComponent(Toolbar, {});
|
||||
|
||||
|
||||
/*
|
||||
Used to find and register headers in a view, and this directive's
|
||||
content will be moved up to the common toolbar location, and created
|
||||
using the same context as the view's content area.
|
||||
*/
|
||||
@Directive({
|
||||
selector: 'template[header]'
|
||||
})
|
||||
export class HeaderTemplate {
|
||||
constructor(navItem: NavItem, protoViewRef: ProtoViewRef) {
|
||||
navItem.addHeader(protoViewRef);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
// Toolbar
|
||||
// --------------------------------------------------
|
||||
|
||||
$toolbar-background: #f7f7f8 !default;
|
||||
$toolbar-background-color: #fff !default;
|
||||
|
||||
$toolbar-order: (
|
||||
back-button: 10,
|
||||
title: 20,
|
||||
@@ -11,22 +12,11 @@ $toolbar-order: (
|
||||
);
|
||||
|
||||
|
||||
.toolbar-container {
|
||||
background: $toolbar-background;
|
||||
}
|
||||
|
||||
ion-toolbar {
|
||||
background: $toolbar-background-color;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
// by default ion-toolbar is display:none and
|
||||
// the transition animation will add the show class
|
||||
display: none;
|
||||
|
||||
&.show-toolbar {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar-inner {
|
||||
|
||||
Reference in New Issue
Block a user