View / Router

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

Let’s look at view HTML structure:

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 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!

  1. <body>
  2. <!-- app root -->
  3. <div id="app">
  4. <!-- view inside of panel -->
  5. <div class="panel panel-left panel-cover">
  6. <div class="view panel-view"> ... </div>
  7. </div>
  8. <!-- Views container -->
  9. <div class="views tabs">
  10. <!-- Your main view -->
  11. <div class="view view-main tab tab-active" id="view-1">
  12. <!-- View related pages -->
  13. ...
  14. </div>
  15. <!-- Another view -->
  16. <div class="view tab" id="view-2">
  17. <!-- View related pages -->
  18. ...
  19. </div>
  20. ...
  21. </div>
  22. <div class="popup">
  23. <div class="view popup-view"> ... </div>
  24. </div>
  25. </div>
  26. </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:

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

  1. var app = new Framework7({
  2. view: {
  3. iosDynamicNavbar: false,
  4. xhrCache: false,
  5. }
  6. });

So to create View we have to call:

  1. 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 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:

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 to navigate between pages. And we can pass additional navigation parameters using data- attributes:

  1. <!-- same as router.navigate('/somepage/'); -->
  2. <a href="/somepage/">Some Page</a>
  3. <!-- same as router.navigate('/somepage/', {reloadCurrent: true, animate: false}); -->
  4. <a href="/somepage/" data-animate="false" data-reload-current="true">Some Page</a>
  5. <!-- same as router.back(); -->
  6. <a href="#" class="back">Go back</a>
  7. <!-- same as router.back('/home/', {force: true, ignoreCache: true}); -->
  8. <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

  1. <!-- left view -->
  2. <div class="view view-init view-left" data-name="left">
  3. ...
  4. <!-- will load "some-page" to main view -->
  5. <a href="/some-page/" data-view=".view-main">Some Page</a>
  6. ...
  7. </div>
  8. <!-- main view -->
  9. <div class="view view-init view-main">
  10. ...
  11. <!-- will load "another-page" to left view -->
  12. <a href="/another-page/" data-view=".view-left">Another Page</a>
  13. ...
  14. </div>

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

  1. <a href="/some-page/" class="prevent-router">Some Page</a>

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

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:

  1. <!-- Add view-init class -->
  2. <div class="view view-init">
  3. ...
  4. </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

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
  1. <!-- main view -->
  2. <div class="view view-main view-init">
  3. ...
  4. </div>
  5. <!-- another view -->
  6. <div class="view view-init" data-name="home">
  7. ...
  8. </div>
  1. var mainView = app.views.main;
  2. 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:

  1. <body>
  2. <div id="app">
  3. <div class="view view-main"></div>
  4. </div>
  5. </body>

In routes we may specify “home” route, for example:

  1. routes: [
  2. {
  3. path: '/',
  4. url: './home.html'
  5. },
  6. ...
  7. ]

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

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

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:

  • you need to specify masterDetailBreakpoint View’s parameter
  • set master: true property on Master route
  • in addition we can put all detail routes in of master route

For example:

  1. const mainView = app.views.create('.view-main', {
  2. // enable master detail
  3. masterDetailBreakpoint: 800,
  4. routes: [
  5. {
  6. path: '/',
  7. url: './pages/master.html',
  8. // specify home route as master route
  9. master: true,
  10. // detail routes
  11. detailRoutes: [
  12. {
  13. path: '/detail/:id/',
  14. url: './pages/detail.html',
  15. },
  16. ]
  17. },
  18. ]

And we should have something like below: