View / Router

View (<div class="view">) - is a separate visual part of the app with its own settings, navigation and history. So it is some kind of app in app. Such kind of functionality allows you easily manipulate each part of your app.

View Layout

Let's look at view HTML structure:

<body>
  <!-- app root -->
  <div id="app">
    <!-- view inside of panel -->
    <div class="panel panel-left panel-cover">
      <div class="view panel-view"> ... </div>
    </div>
    <!-- Your main view -->
    <div class="view view-main">
      <!-- View related pages -->
      ...
    </div>
    <div class="popup">
      <div class="view popup-view"> ... </div>
    </div>
  </div>
</body>

As you see View may be almost in any part of your app.

Main View

Your main view should have additional view-main class. Why we need main view? By default all links (which is not in any initialized view) will load pages in main view. Also if you use pushState hash navigation then it works only for main view's navigation.

Multiple Views Layout

In case we have the app with multiple views in app root, so called "Tabbed Views" app, we must wrap our views with additional <div class="views"> element.

Only one "Views" element is allowed!

<body>
  <!-- app root -->
  <div id="app">
    <!-- view inside of panel -->
    <div class="panel panel-left panel-cover">
      <div class="view panel-view"> ... </div>
    </div>
    <!-- Views container -->
    <div class="views tabs">
      <!-- Your main view -->
      <div class="view view-main tab tab-active" id="view-1">
        <!-- View related pages -->
        ...
      </div>
      <!-- Another view -->
      <div class="view tab" id="view-2">
        <!-- View related pages -->
        ...
      </div>
      ...
    </div>
    <div class="popup">
      <div class="view popup-view"> ... </div>
    </div>
  </div>
</body>

View App Methods

When we already have required views in HTML and our app is already initialized, now we need to initialize our views. Let's look at available app methods to work with Views:

app.views.create(viewEl, parameters) - initialize View

  • viewEl - string or HTMLElement. If string - CSS selector of View element
  • parameters - object. Object with View parameters
  • Method returns object with just created View instance.

app.views.get(viewEl) - get View instance by HTML element

  • viewEl - string or HTMLElement. If string - CSS selector of View element
  • Method returns object with just created View instance.

There could be situation when we need to get currently active View, because instead of main app view we may also have view in opened popup, popover, opened panel, tabs, etc. This method allows to get the View instance of currently active/visible/"most-top" view.

For example, if you have initilized View in panel, and panel is currently opened, then this method will return panel's view. Or, if you use app with tab bar layout, where each tab is view, then this method will return currently active/visible tab-view

app.views.current - get currently active/visible View instance.

  • Method returns object with just created View instance.

View Parameters

Now let's look at list of available parameters we need to create View:

ParameterTypeDefaultDescription
namestringView name. If view was created with name, then it may be accessed via app.views.[name]
mainbooleanfalseSpecify whether this is View is main or not. If not passed then will be determined based on whether its element has view-main class or not
routerbooleantrueSet to false to disable view router
urlstringDefault (initial) View's url. If not specified, then it is equal to document url
stackPagesbooleanfalseIf enabled then all previous pages in navigation chain will not be removed from DOM when you navigate deeper and deeper. It could be useful, for example, if you have some Form from 5 steps (5 pages) and when you are on last 5th page you need access to form that was on 1st page.
linksViewstring
object
CSS Selector of another view or object with initialized View instance. By defaul all links in initialized (only) view will load pages in this view. This tell links to load pages in other view.
allowDuplicateUrlsbooleanfalseYou may enable this parameter to allow loading of new pages that have same url as currently "active" page in View.
animatebooleantrueEnables transitions between pages
preloadPreviousPagebooleantrueEnable/disable preloading of previous page when you go deep in navigation. Should be enabled for correct work of "swipe back page" feature.
reloadPagesbooleanfalseWhen enabled, View will always reload currently active page without loading new one
restoreScrollTopOnBackbooleantrueWhen enabled it will restore page scroll top when you get back to this page
iosPageLoadDelaynumber0Delay (in ms) after new page will be loaded and inserted to DOM and before it will be transitioned. Can be increased a bit to improve performance. Will have effect only under iOS theme
mdPageLoadDelaynumber0Delay (in ms) after new page will be loaded and inserted to DOM and before it will be transitioned. Can be increased a bit to improve performance. Will have effect only under MD theme
auroraPageLoadDelaynumber0Delay (in ms) after new page will be loaded and inserted to DOM and before it will be transitioned. Can be increased a bit to improve performance. Will have effect only under iOS theme
passRouteQueryToRequestbooleantrueWhen enabled then router will pass route url query to request url query (for url, templateUrl and componentUrl route properties)

If you have the following route:

{ path: '/somepage/', url: 'http://myserver/page/' }

and you will click link with /somepage/?foo=bar url then it will load page from http://myserver/page/?foo=bar url

passRouteParamsToRequestbooleanfalseWhen enabled then router will pass current route parameters to request url query (for url, templateUrl and componentUrl route properties)

If you have the following route:

{ path: '/user/:userId/posts/:postId/', url: 'http://myserver/userpost/' }

and you will click link with /user/11/posts/12/ url then it will load page from http://myserver/userpost/?userId=11&postId=12 url

Master Detail
masterDetailBreakpointnumber0Minimum app width to enable Master Detail view for master routes (routes with master: true parameter)
reloadDetailbooleanfalseWhen enabled it will reload every detail page when navigating
Routes
routesarrayArray with current View routes. In case if specified then will overwrite global app routes and routes only specified here will be available for the current View
routesAddarrayArray with additional routes that will extend global app routes. This additional routes will only be available for the current View
routesBeforeEnterfunction(to, from, resolve, reject)

array
Function (or array of functions) that will be executed before every route load/enter. To proceed route loading resolve must be called. In case of array then every function in array must be resolved to proceed.

Same as route beforeEnter but will work for every route

routesBeforeLeavefunction(to, from, resolve, reject)

array
Function (or array of functions) that will be executed before every route unload/leave. To proceed navigation resolve must be called. In case of array then every function in array must be resolved to proceed.

Same as route beforeLeave but will work for every route

Elements Removal
removeElementsbooleantrueDuring page transitions Router may remove unused Page and Navbar elements from DOM. Useful to be disabled in case you want to handle elements removal manually or using other library, e.g. Vue or React
removeElementsWithTimeoutbooleanfalseWhen enabled then Router will remove elements after timeout
removeElementsTimeoutnumber0Timeout to remove elements (in case of removeElementsWithTimeout: true)
unloadTabContentbooleantrueUnloads routable tab content (removes tab inner content) when tab becomes visible. Only for routable tabs
XHR Cache
xhrCachebooleantrueAs Router can use Ajax to load HTML content for pages it is good to use caching, especially if your content in those pages updates not very often.
xhrCacheIgnoreboolean[]Array of URLs (string) that should not be cached
xhrCacheIgnoreGetParametersbooleanfalseIf "true" then URLs like "about.html?id=2" and "about.html?id=3" will be treated and cached like single "about.html" page
xhrCacheDurationboolean1000 * 60 * 10Duration in ms (milliseconds) while app will use cache instead of loading page with another Ajax request. By default it takes 10 minutes.
iOS Dynamic Navbar
iosDynamicNavbarbooleantrueEnables dynamic navbar for iOS theme
iosSeparateDynamicNavbarbooleantrueWhen enabled will extract dynamic navbar HTML element from page element and put it as a child of Views element. It improves dynamic navbar transition appearance, but in case you need dynamic navbar to be always as a page's child, then disable this parameter
iosAnimateNavbarBackIconbooleantrueThis option (when enabled) gives more native look for dynamic navbar left back-link icon animation. Useful only when you use dynamic navbar with default back-link icon on left side set as "sliding".
Swipe back
iosSwipeBackbooleantrueEnable/disable ability to swipe back from left edge of screen to get to the previous page. For iOS theme
iosSwipeBackThresholdnumber0Value in px. Swipe back action will start if "touch distance" will be more than this value. For iOS theme
iosSwipeBackActiveAreanumber30Value in px. Width of invisible left edge of the screen that triggers swipe back action. For iOS theme
iosSwipeBackAnimateShadowbooleantrueEnable/disable box-shadow animation during swipe back action. You can disable it to improve performance. For iOS theme
iosSwipeBackAnimateOpacitybooleantrueEnable/disable opacity animation during swipe back action. You can disable it to improve performance. For iOS theme
mdSwipeBackbooleanfalseEnable/disable ability to swipe back from left edge of screen to get to the previous page. For MD theme
mdSwipeBackThresholdnumber0Value in px. Swipe back action will start if "touch distance" will be more than this value. For MD theme
mdSwipeBackActiveAreanumber30Value in px. Width of invisible left edge of the screen that triggers swipe back action. For MD theme
mdSwipeBackAnimateShadowbooleantrueEnable/disable box-shadow animation during swipe back action. You can disable it to improve performance. For MD theme
mdSwipeBackAnimateOpacitybooleanfalseEnable/disable opacity animation during swipe back action. You can disable it to improve performance. For MD theme
auroraSwipeBackbooleantrueEnable/disable ability to swipe back from left edge of screen to get to the previous page. For Aurora theme
auroraSwipeBackThresholdnumber0Value in px. Swipe back action will start if "touch distance" will be more than this value. For Aurora theme
auroraSwipeBackActiveAreanumber30Value in px. Width of invisible left edge of the screen that triggers swipe back action. For Aurora theme
auroraSwipeBackAnimateShadowbooleanfalseEnable/disable box-shadow animation during swipe back action. You can disable it to improve performance. For Aurora theme
auroraSwipeBackAnimateOpacitybooleantrueEnable/disable opacity animation during swipe back action. You can disable it to improve performance. For Aurora theme
Push State
pushStatebooleanfalseIf you develop web app (not PhoneGap or Home Screen web app) it is useful to enable hash navigation (browser url will look like "http://my-webapp.com/#!/about.html"). User as well will be able to navigate through app's history by using browser's default back and forward buttons.
pushStateRootstringPush state root URL separator, for example "http://my-app.com/". It is useful only in case when you use empty ("") pushStateSeparator
pushStateAnimatebooleantrueEnable/disable page transitions on push state change
pushStateAnimateOnLoadbooleanfalseEnable/disable push state page transition on app load
pushStateSeparatorstring#!Push state URL separator, can be changed for something like '#page/' and then your push state urls will look like "http://myapp.com/#page/about.html"
pushStateOnLoadbooleantrueDisable to ignore parsing push state URL and loading page on app load
Events Handlers
onobjectObject with events handlers. For example:
var view = app.views.create('.view-main', {
  on: {
    pageInit: function () {
      console.log('page init')
    }
  }
})

Note that all following parameters can be used in global app parameters under view property to set defaults for all views. For example:

var app = new Framework7({
  view: {
    iosDynamicNavbar: false,
    xhrCache: false,
  }
});

View Methods & Properties

So to create View we have to call:

var view = app.views.create({ /* parameters */ })

After that we have its initialized instance (like view variable in example above) with useful methods and properties:

Properties
view.appLink to global app instance
view.elView HTML element
view.$elDom7 instance with view HTML element
view.nameView name that was passed name parameter
view.mainBoolean property indicating is it a main view or not
view.routesArray with available router's routes
view.historyArray with view history
view.paramsObject with view initialization parameters
view.routerView's initialized router instance
Methods
view.destroy()Destroy view instance
view.on(event, handler)Add event handler
view.once(event, handler)Add event handler that will be removed after it was fired
view.off(event, handler)Remove event handler
view.off(event)Remove all handlers for specified event
view.emit(event, ...args)Fire event on instance

View Events

View will fire the following DOM events on view element and events on app and view instance:

View Dom Events

EventTargetDescription
view:initView Element<div class="view">Event will be triggered on view initialization

View Instance Events

View instance emits events on both self instance and app instance. App instance events has same names prefixed with view.

EventTargetArgumentsDescription
initview(view)Event will be triggered on view initialization
viewInitapp

Router API / Methods & Properties

View's main purpose is a navigating/routing between pages. We can access its router instance by view.router. It has a lot of useful methods and properties to take control over routing and navigation:

Router Properties
router.appLink to global app instance
router.viewLink to related View instance
router.paramsObject with router initialization parameters
router.elRouter's view HTML element
router.$elDom7 instance with router's view HTML element
router.currentPageElDom7 instance with current page HTML element
router.routesArray with available router's routes
router.historyArray with router's view history
router.cacheObject with router/view cache data
router.currentRouteObject with current route data. It has the following properties
  • url - route URL
  • path - route path
  • query - object with route query. If the url is /page/?id=5&foo=bar then it will contain the following object {id: '5', foo: 'bar'}
  • params - route params. If we have matching route with /page/user/:userId/post/:postId/ path and url of the page is /page/user/55/post/12/ then it will be the following object {userId: '55', postId: '12'}
  • name - route name
  • hash - route URL hash
  • route - object with matching route from available routes
  • context - context that was passed to the route
router.previousRouteObject with previously active route data. Same object format as currentRoute
router.allowPageChangeBoolean property indicating is it allowed to change page / navigate or not
Router Methods
router.navigate(url, options)Navigate to (load) new page
  • url string - url to navigate to
  • options - object with additional navigation properties (optional):
    • reloadCurrent (boolean) - replace the current page with the new one from route, no animation in this case
    • reloadPrevious (boolean) - replace the previous page in history with the new one from route
    • reloadAll (boolean) - load new page and remove all previous pages from history and DOM
    • clearPreviousHistory (boolean) - previous pages history will be cleared after reloading/navigate to the specified route
    • animate (boolean) - whether the page should be animated or not (overwrites default router settings)
    • history (boolean) - whether the page should be saved in router history
    • pushState (boolean) - whether the page should be saved in browser state. In case you are using pushState, then you can pass here false to prevent route getting in browser history
    • ignoreCache (boolean) - If set to true then it will ignore if such URL in cache and reload it using XHR again
    • context (object) - additional Router component or Template7 page context
    • props (object) - props that will be passed as Vue/React page component props
router.navigate(parameters, options)Navigate to (load) new page by parameters. This method allows to navigate to route by its name.
  • parameters object - object with route name, query, params to navigate to.
  • options - object with additional navigation properties (optional). Same as in previous example.

For example, if we have the following route:

{
  name: 'about',
  path: '/about/',
  ...
}

We can navigate to it by calling:

router.navigate({ name: 'about' });

If have more complex route with params:

{
  name: 'post',
  path: '/block/:userId/:postId',
  ...
}

Then it is mandatory to pass params as well:

router.navigate({
  name: 'about',
  params: { userId: 1, postId: 2 },
});
router.back(url, options)Go back to previous page, going back in View history
  • url string - url to navigate to (optional).
    • If not specified, then it will go back to the previous page in history.
    • If specified and there is previous page in history then it will be ignored.
    • If specified and there is a force: true option then will remove previous page from DOM and navigate back to the specified page URL
  • options - object with additional navigation properties (optional):
    • animate (boolean) - whether the page should be animated or not (overwrites default router settings)
    • pushState (boolean) - whether the page should be saved in browser state. In case you are using pushState, then you can pass here false to prevent route getting in browser history
    • ignoreCache (boolean) - If set to true then it will ignore if such URL in cache and reload it using XHR again
    • force (boolean) - if set to true then it will ignore previous page in history and load specified one
router.refreshPage()Refresh/reload current page. Actually same as:
router.navigate(router.currentRoute.url, {
  reloadCurrent: true,
  ignoreCache: true,
});
router.clearPreviousHistory()Clear router previous pages history and remove all previous pages from DOM
router.clearPreviousPages()Works mostly like clearPreviousHistory but only removes previous pages from DOM
router.updateCurrentUrl(url)Updates current route url, and updates router.currentRoute properties (query, params, hash, etc.) based on passed url. This method doesn't load or reload any content. It just changes current route url.
router.on(event, handler)Add event handler
router.once(event, handler)Add event handler that will be removed after it was fired
router.off(event, handler)Remove event handler
router.off(event)Remove all handlers for specified event
router.emit(event, ...args)Fire event on instance

Linking Between Pages & Views

It may be not very comfortable to use router methods all the time to navigate between pages. In many cases we can just use links to navigate between pages. And we can pass additional navigation parameters using data- attributes:

<!-- same as router.navigate('/somepage/'); -->
<a href="/somepage/">Some Page</a>

<!-- same as router.navigate('/somepage/', {reloadCurrent: true, animate: false}); -->
<a href="/somepage/" data-animate="false" data-reload-current="true">Some Page</a>

<!-- same as router.back(); -->
<a href="#" class="back">Go back</a>

<!-- same as router.back('/home/', {force: true, ignoreCache: true}); -->
<a href="/home/" data-force="true" data-ignore-cache="true" class="back">Go back</a>

Links default behavior:

  • If link is in inside of not initialized view then it will load page in main view
  • If link is in inside of initialized view then it will load page in this view (if other view is not specified in view's linksView parameter)

But if we need to load page in another view we can specify this view's CSS selector in link's data-view attribute

<!-- left view -->
<div class="view view-init view-left" data-name="left">
  ...
  <!-- will load "some-page" to main view -->
  <a href="/some-page/" data-view=".view-main">Some Page</a>
  ...
</div>
<!-- main view -->
<div class="view view-init view-main">
  ...
  <!-- will load "another-page" to left view -->
  <a href="/another-page/" data-view=".view-left">Another Page</a>
  ...
</div>

If we need to prevent router from handling specific links, we can add prevent-router class to such links:

<!-- This link will be ignored by router -->
<a href="/some-page/" class="prevent-router">Some Page</a>

Router Events

Router has a lot of useful events.

Router Dom Events

Router will fire the following DOM events for swipe back pages:

EventTargetDescription
swipeback:moveView Element<div class="view">Event will be triggered during swipe back move
swipeback:beforechangeView Element<div class="view">Event will be triggered right before swipe back animation to previous page when you release it
swipeback:afterchangeView Element<div class="view">Event will be triggered after swipe back animation to previous page when you release it
swipeback:beforeresetView Element<div class="view">Event will be triggered right before swipe back animation to current page when you release it
swipeback:afterresetView Element<div class="view">Event will be triggered after swipe back animation to current page when you release it

Router Instance Events

Router events bubble to View instance and to the App instance, so the event emitted on router instance will also be avaiable on view and on app instances:

EventArgumentsDescription
routeChange(newRoute, previousRoute, router)Event will be fired on current route change
routeChanged(newRoute, previousRoute, router)Event will be fired on current route change and after page transitions
routeUrlUpdate(newRoute, router)Event will be fired when router.updateCurrentUrl method called
XHR Events
routerAjaxStart(xhr, options)Event will be fired after router XHR opened and before XHR send. Can be used to modify the XHR object before it is sent. Use this callback to set custom headers, etc. As an arguments receives XHR object and navigating options object
routerAjaxSuccess(xhr, options)Event will be fired when the request succeeds. As an arguments receives XHR object and navigating options object
routerAjaxError(xhr, options)Event will be fired if the request fails. As an arguments receives XHR object and navigating options object
routerAjaxComplete(xhr, options)Event will be fired when the request finishes. As an arguments receives XHR object and navigating options object
Swipe Back Events
swipebackMove(data)Event will be triggered during swipe back move. data contains object with the following properties: percentage, currentPageEl, previousPageEl, currentNavbarEl, previousNavbarEl
swipebackBeforeChange(data)Event will be triggered right before swipe back animation to previous page when you release it. data contains object with the following properties: currentPageEl, previousPageEl, currentNavbarEl, previousNavbarEl
swipebackAfterChange(data)Event will be triggered after swipe back animation to previous page when you release it. data contains object with the following properties: currentPageEl, previousPageEl, currentNavbarEl, previousNavbarEl
swipebackBeforeReset(data)Event will be triggered right before swipe back animation to current page when you release it. data contains object with the following properties: currentPageEl, previousPageEl, currentNavbarEl, previousNavbarEl
swipebackAfterReset(data)Event will be triggered after swipe back animation to current page when you release it. data contains object with the following properties: currentPageEl, previousPageEl, currentNavbarEl, previousNavbarEl
Page Events
pageMounted(pageData)Event will be triggered when new page just inserted to DOM. Or when page with keepAlive route is mounted/attached to DOM. As an argument event receives Page Data
pageInit(pageData)Event will be triggered after Router initialize required page's components and navbar. As an argument event receives Page Data
pageReinit(pageData)This event will be triggered in case of navigating to the page that was already initialized. As an argument event receives Page Data
pageBeforeIn(pageData)Event will be triggered when everything initialized and page is ready to be transitioned into view (into active/current position). As an argument event receives Page Data
pageAfterIn(pageData)Event will be triggered after page transitioned into view. As an argument event receives Page Data
pageBeforeOut(pageData)Event will be triggered right before page is going to be transitioned out of view. As an argument event receives Page Data
pageAfterOut(pageData)Event will be triggered after page transitioned out of view. As an argument event receives Page Data
pageBeforeUnmount(pageData)Event will be triggered when page with keepAlive route is going to be unmounted/detached from DOM. As an argument event receives Page Data
pageBeforeRemove(pageData)Event will be triggered right before Page will be removed from DOM. This event could be very useful if you need to detach some events / destroy some plugins to free memory. As an argument event receives Page Data. This event won't be triggered for keepAlive routes.
Routable Tabs Events
tabInit
tabMounted
(newTabEl, tabRoute)Event will be triggered right after routable Tab content will be loaded. As an argument event handler receives:
  • newTabEl - tab HTML element where route content was just loaded (new tab)
  • tabRoute - new tab route
tabBeforeRemove(oldTabEl, newTabEl, tabRoute)Event will be triggered right after routable Tab content will be loaded. As an argument event handler receives:
  • oldTabEl - tab HTML element where route content was just removed (old tab)
  • newTabEl - tab HTML element where route content was just loaded (new tab)
  • tabRoute - new tab route
Routable Modals Events
modalInit
modalMounted
(modalEl, modalRoute, modal)Event will be triggered right after routable modal content will be loaded and added to DOM. As an argument event handler receives:
  • modalEl - loaded modal HTML element
  • modalRoute - modal route
  • modal - created modal instance
modalBeforeRemove(modalEl, modalRoute, modal)Event will be triggered right before routable modal will be removed from DOM and destroyed. As an argument event handler receives:
  • modalEl - modal HTML element
  • modalRoute - modal route
  • modal - modal instance

View Auto Initialization

If you don't need to use View API and your View is inside of DOM on a moment of app initialization then it can be auto initialized with just adding additional view-init class:

<!-- Add view-init class -->
<div class="view view-init">
  ...
</div>

But what about View parameters. In this case we may pass them in data- attributes.

Parameters that used in camelCase, for example pushState, in data- attributes should be used as kebab-case as data-push-state

<!-- view parameters in data- attributes -->
<div class="view view-init" data-url="/" data-name="home" data-push-state="true">
  ...
</div>

In this case if you need to access created View instance you can use:

  • In case if it is main view, we may use app.views.main to get main view instance
  • Otherwise, we can access it by passed name parameter like app.views.home
<!-- main view -->
<div class="view view-main view-init">
  ...
</div>

<!-- another view -->
<div class="view view-init" data-name="home">
  ...
</div>
var mainView = app.views.main;
var homeView = app.views.home;

Initial Page Route

Initial page can also be loaded correctly using Routes. In app layout we must leave View blank:

<body>
  <div id="app">
    <div class="view view-main"></div>
  </div>
</body>

In routes we may specify "home" route, for example:

routes: [
  {
    path: '/',
    url: './home.html'
  },
  ...
]

And when we init the View, we need to specify it is default URL:

app.views.create('.view-main', {
  url: '/'
})

That is all, now on app load, home page content will be loaded from "home.html" file.

Master Detail

Master-Detail pattern oftenly used on wide enough screens and tablets, and consists of two views:

  • Master - is the area in the UI where you have a list of something.
  • Detail - is the area that shows the relevant information of a selection in the master.

When collapsed (on narrow screen) navigation between such pages will behave as usual routing.

Navigation to/from Master-Detail view happens without transition.

When Master page is loaded all other pages will be loaded as Detail pages. To "navigate away" from Master Detail view it is recommended to use reloadAll navigation parameter.

To enable Master Detail:

For example:

const mainView = app.views.create('.view-main', {
  // enable master detail
  masterDetailBreakpoint: 800,
  routes: [
    {
      path: '/',
      url: './pages/master.html',
      // specify home route as master route
      master: true,
      // detail routes
      detailRoutes: [
        {
          path: '/detail/:id/',
          url: './pages/detail.html',
        },
      ]
    },
  ]
});

And we should have something like below: