Migration To Framework7 v2

Stable Framework7 v2 was recently released with the new v2 documentation. And in case you have already created or started to work on app with Framework7 v1 you may want to switch it to v2.

Do you need to switch? Well, in case you have a fully functional and released app made with v1, and you are not going to implement there new features and you are happy with its performance and functionality then you, probably, don't need to change your app to v2. But in case your app is still in development or you are going to release updates for your existing app then v2 is a must. It has much more features, less bugs, and of course this is the main version/branch that will be maintained in future (including new features and bug fixes).

In this guide we will check what need to be done/changed in your Framework7 v1 app to switch it to v2. Note, this guide is for vanilla Framework7 version, Framework7-Vue/React guides will be published later.

Assets

First of all, new F7 has new JS & CSS assets structure.

Stylesheets

  • now there is no more separate "colors" stylesheet, all color themes are embedded now into main stylesheets
  • there is no more additional RTL stylesheet that you added in addition to main stylesheet to enable RTL styles. Now it is standalone stylesheet file that must be included instead of usual/ltr one
  • theme-related styles (for iOS theme and MD theme) are also now in main styles

So here is the list of stylesheet files you will find in /dist/css/ folder:

  • framework7.css - main styles bundle. Contains everything in default (LTR) direction: all color themes, iOS theme and MD theme
  • framework7.ios.css - contains iOS-only style. Useful only in case you develop app with only iOS theme
  • framework7.md.css - contains MD-only style. Useful only in case you develop app with only MD theme
  • framework7.rtl.css - RTL bundle. Contains everything in RTL direction: all color themes, iOS theme and MD theme
  • framework7.rtl.ios.css - RTL styles only for iOS theme. Useful only in case you develop RTL app with only iOS theme
  • framework7.rtl.md.css - RTL only for MD theme. Useful only in case you develop RTL app with only MD theme

And same minified files:

  • framework7.min.css
  • framework7.md.min.css
  • framework7.ios.min.css
  • framework7.rtl.min.css
  • framework7.rtl.ios.min.css
  • framework7.rtl.md.min.css

So if in v1 you have supported both iOS and MD themes you had conditional include of the framework7.ios.css + framework7.ios.colors.css + framework7.material.css + framework7.material.colors.css. Now you need to include only one stylesheet framework7.css (or its minified version).

If you used RTL layout with both themes, you had even more files included: framework7.ios.css + framework7.ios.colors.css + framework7.ios.rtl.css + framework7.material.css + framework7.material.colors.css + framework7.material.rtl.css. Now you need to include only one stylesheet framework7.rtl.css (or its minified version).

Scripts

In terms of script files not much changed in case you included them via <script> attribute. There are same scripts you will find in /dist/js/ folder:

  • framework7.js - Framework7 library with all its components
  • framework7.min.js - its minified version

But if you included it using ES import then there are a lot of new things here, now Framework7 and all of its components available as ES modules, check the Installation Docs

App HTML Layout

HTML layout of many components and main app layout is a bit changed. In v1 we had:

<body>
  <!-- Statusbar overlay -->
  <div class="statusbar-overlay"></div>
  <!-- Panels -->
  <div class="panel panel-left">...</div>
  <div class="panel panel-right">...</div>
  <!-- Views -->
  <div class="views">
    <!-- Your main view, should have "view-main" class -->
    <div class="view view-main">
      <!-- Pages container, because we use fixed navbar and toolbar, it has additional appropriate classes-->
      <div class="pages navbar-through toolbar-fixed">
        <!-- Page, "data-page" contains page name -->
        <div data-page="index" class="page"></div>
      </div>
    </div>
  </div>
</body>
<!-- Navbar -->
<div class="navbar">
  <div class="navbar-inner">
    <div class="center">Awesome App</div>
  </div>
</div>
<!-- Toolbar -->
<div class="toolbar">
  <div class="toolbar-inner">
    <!-- Toolbar links -->
    <a href="#" class="link">Link 1</a>
    <a href="#" class="link">Link 2</a>
  </div>
</div>
<!-- Scrollable page content -->
<div class="page-content">
  <p>Page content goes here</p>
  <!-- Link to another page -->
  <a href="about.html">About app</a>
</div>

What we need to change here:

  • statusbar-overlay has been renamed to just statusbar. Check Statusbar docs
  • views element is not required anymore for single view app. It is only required for so called "Tabbed app layout" with multiple views-tabs. Check App Layout docs
  • data-page page's attribute renamed to data-name and also not required anymore
  • All navbar/toolbar related layout classes are gone and not used anymorenavbar-through, navbar-fixed, toolbar-through, toolbar-fixed, etc. Check Navbar and Toolbar docs
  • <div class="pages"> element that was used to wrap all view's pages is also gone and not needed anymore
  • It is now recommended to wrap an app into single root element, for example <div id="#app"></div
  • Navbar's center element renamed to title

So in v2 we will have the following:

<body>
  <!-- App root -->
  <div id="app">
    <!-- Just "statusbar" now -->
    <div class="statusbar"></div>
    <!-- Panels -->
    <div class="panel panel-left">...</div>
    <div class="panel panel-right">...</div>
    <!-- No more views -->
    <div class="view view-main">
      <!-- No more "pages" element and navbar/toolbar related classes -->
      <!-- "data-page" renamed to "data-name" -->
      <div data-name="index" class="page">
        <!-- Navbar and Toolbar are always first elements in the page-->

        <!-- Navbar -->
        <div class="navbar">
          <div class="navbar-inner">
            <div class="title">Awesome App</div>
          </div>
        </div>

        <!-- Toolbar -->
        <div class="toolbar">
          <div class="toolbar-inner">
            <!-- Toolbar links -->
            <a href="#" class="link">Link 1</a>
            <a href="#" class="link">Link 2</a>
          </div>
        </div>

        <!-- Scrollable page content -->
        <div class="page-content">
          <p>Page content goes here</p>
          <!-- Link to another page -->
          <a href="about.html">About app</a>
        </div>
      </div>
    </div>
  </div>
  ...
</body>

One more important change, now whole HTML structure must be the same for both iOS and MD themes. There is no more any layout difference between them!

iOS Dynamic Navbar

One of the v1 pains was Dynamic Navbar structure, v1 required you to put it under View element outside of Page, this produced a lot inconvenience in case you have to maintained both iOS and MD themes in your app. Now such requirement is gone as well, and now Navbar must be always a direct child of the page, and F7 will automatically move it under the View element if it is necessary.

New Components API

First of all, there is a new components API structure. All components that require initialization have new API now. For example in v1 to init/create component we had to call something like app.[componentName](params), for example:

  • app.popup(...) - to create and open Popup
  • app.virtualList(...) - to create Virtual List
  • app.calendar(...) - to create Calendar

In v2 all components API naming convention is new. It is now app.[componentName].create(params), for example:

  • app.popup.create(...) - to create Popup instance
  • app.virtualList.create(...) - to create Virtual List
  • app.calendar.create(...) - to create Calendar

All these .create() methods return initialized component instance with own methods, events and properties. For example:

var popup = app.popup.create(...);
// open popup
popup.open();

There are also new additional app methods for such components:

  • app.[componentName].get(el) - returns initialized component instance (with .create) by passed HTML element
  • app.[componentName].destroy(el) - destroys initialized component instance by passed HTML element

And some components has additional app methods related to components. So if you use components with initialization then it is highly recommended to check their documentation.

New/Reworked Components Layout

HTML layout structure of many components has been changed, renamed or simplified. Here are some changes for commonly used components:

List View

  • List element class changed from list-block to just list

Content Block

  • Content Block. Content block element class changed from content-block to just block
  • Content block title element class changed from content-block-title to just block-title
  • content-block-inner element (for additional block highlighting) has beed removed and replaced with just an additional block-strong class on the block, so now it should be <div class="block block-strong">...</div>

Navbar

  • As mentioned above, its center element with page title renamed to title

Subnavbar

Subnavbar content must be wrapped with additional <div class="subnavbar-inner">...</div> element:

<div class="subnavbar">
  <div class="subnavbar-inner">... subnavbar links or buttons ...</div>
</div>

Form Inputs

Form inputs layout that used in List View a bit changed:

  • List item's item-content element that contains form input must have additional item-input class. In v1 "item-input" class was added to input element itself
  • Input element itself must be wrapped with additional <div class="item-input-wrap"></div> element
  • Input label element now is <div class="item-title item-label"> . In v1 it was <div class="item-title label">
<!-- So, in v1 it was: -->
<li>
  <div class="item-content">
    <div class="item-media">... icon/image here ...</div>
    <div class="item-inner">
      <div class="item-title label">Name</div>
      <div class="item-input">
        <input type="text" name="name" />
      </div>
    </div>
  </div>
</li>
<!-- In v2 the same will be: -->
<li class="item-content item-input">
  <div class="item-media">... icon/image here ...</div>
  <div class="item-inner">
    <div class="item-title item-label">Name</div>
    <div class="item-input-wrap">
      <input type="text" name="name" />
      <span class="input-clear-button"></span>
    </div>
  </div>
</li>

And now all input labels are stacked by default (not inline like in v1), there are also a lot of new additional elements and configuration for input elements. Check the Form Inputs docs for more info

Messages

Well, Messages component has been fully reworked, so everything is new here from html layout to API. So it is worth to check Messages docs

Searchbar

Searchbar has a bit changed layout:

<!-- In v1: -->
<form class="searchbar">
  <div class="searchbar-input">
    <input type="search" placeholder="Search" />
    <a href="#" class="searchbar-clear"></a>
  </div>
  <a href="#" class="searchbar-cancel">Cancel</a>
</form>
<!-- In v2: -->
<form class="searchbar">
  <div class="searchbar-inner">
    <div class="searchbar-input-wrap">
      <input type="search" placeholder="Search" />
      <i class="searchbar-icon"></i>
      <span class="input-clear-button"></span>
    </div>
    <span class="searchbar-disable-button">Cancel</span>
  </div>
</form>

Where we can see:

  • new additional "search-inner" element to wrap searchbar content
  • "searchbar-input" renamed to "searchbar-input-wrap"
  • new seach icon
  • "searchbar-clear" renamed to "input-clear-button"
  • "searchbar-cancel" renamed to "searchbar-disable-button"

And of course there is new API. Check the Searchbar component docs

Floating Action Button (FAB)

FAB layout and API is also changed to be more unified across iOS and MD themes and support new features, including fab position specific classes.

<!-- In v1 we had: -->
<a href="#" class="floating-button">
  <i class="icon icon-plus"></i>
</a>
<!-- Now in v2 it is: -->
<div class="fab fab-right-bottom">
  <a href="#">
    <i class="icon f7-icons">add</i>
  </a>
</div>

FAB Speed Dial comes with new layout as well:

<!-- In v1 it was: -->
<div class="speed-dial">
  <a href="#" class="floating-button">
    <i class="icon icon-plus"></i>
    <i class="icon icon-close"></i>
  </a>
  <!-- Speed Dial Actions -->
  <div class="speed-dial-buttons">
    <a href="#">1</a>
    <a href="#">2</a>
    <a href="#">2</a>
  </div>
</div>
<!-- In v2 it has changed to: -->
<div class="fab fab-right-bottom">
  <a href="#">
    <i class="icon icon-plus"></i>
    <i class="icon icon-close"></i>
  </a>
  <!-- Speed Dial Actions -->
  <div class="fab-buttons fab-buttons-bottom">
    <a href="#">1</a>
    <a href="#">2</a>
    <a href="#">3</a>
  </div>
</div>

Notifications/Toast

In v1 there was a mess with Notification/Toast component, it was rendered similar to native system notification look in iOS theme and as a Toast in MD theme.

In v2 such inconsistency removed and now there are two different components instead:

  • Notification - look like a system notifications on both iOS and MD themes
  • Toast - look like a Toast message on both iOS and MD themes

So just check the Notification and Toast documentation on new API and usage examples

Checkbox/Radio

Checkboxes and radios used in List View now has new and unified layout for both iOS and MD themes:

<div class="list">
  <ul>
    <!-- Single checkbox item -->
    <li>
      <label class="item-checkbox item-content">
        <!-- Checkbox input -->
        <input type="checkbox" />
        <!-- Checkbox icon -->
        <i class="icon icon-checkbox"></i>
        <div class="item-inner">
          <!-- Checkbox Title -->
          <div class="item-title">Books</div>
        </div>
      </label>
    </li>
    <!-- Single radio item -->
    <li>
      <label class="item-radio item-content">
        <!-- Radio input -->
        <input type="radio" name="my-radio" value="radio-1" />
        <!-- Radio icon -->
        <i class="icon icon-radio"></i>
        <div class="item-inner">
          <!-- Radio Title -->
          <div class="item-title">Books</div>
        </div>
      </label>
    </li>
    ...
  </ul>
</div>

Tabs

There is not much changes in Tabs:

  • Active tab HTML element class renamed from active to tab-active
  • API function to show tab changed from app.showTab to app.tab.show

There are also some new features as Routable Tabs, so check the Tabs documentation.

Buttons & Links

Just few changes here:

  • active button element class in Buttons Row/Segmented renamed from active to button-active
  • active tab link element class renamed from active to tab-link-active
  • Buttons Row now called Segmented, so<div class="buttons"> renamed to <div class="segmented">

Check the Button and Link components documentation for all changes and new features.

Switch/Toggle

Switch component in v1 has been renamed to Toggle, it has new HTML layout and now it must be initialized using JavaScript API or auto initialization:

<!-- In v1 -->
<label class="label-switch">
  <input type="checkbox" />
  <div class="checkbox"></div>
</label>
<!-- In v2, with auto init -->
<label class="toggle toggle-init">
  <input type="checkbox" />
  <span class="toggle-icon"></span>
</label>

It is worth to check new Toggle component documentation about all features and new API

Range Slider

As Switch/Toggle, Range Slider now uses JavaScript API and must be initialized manually or automatically in order to work. It has much better support than the older one which was just styled input:range, it has much more new features including dual-range support. Just check Range Slider documentation on how to use it now.

Control Links

As you know there are so called control links in v1, that can trigger some components' actions, like open/close panel, popup, sortable, and other components. In v1 we could have something like:

<!-- Open/Close Panel -->
<a href="#" class="open-panel">Open Panel</a>
<a href="#" class="close-panel">Close Panel</a>
<!-- Open/Close Popup -->
<a href="#" class="open-popup">Open Popup</a>
<a href="#" class="close-popup">Close Popup</a>

In v2 there are same links there only difference is that such additional classes naming convention has beed changed from [action]-[component] (open-panel, close-popup) to [component]-[action] . So the same in v2 will be:

<!-- Open/Close Panel -->
<a href="#" class="panel-open">Open Panel</a>
<a href="#" class="panel-close">Close Panel</a>
<!-- Open/Close Popup -->
<a href="#" class="popup-open">Open Popup</a>
<a href="#" class="popup-close">Close Popup</a>

You can find such links reference in related component documentation, e.g. Control Panel With Links, Control Popup With Links, etc.

Request/Ajax API

Ajax API has been removed from built-in Dom7 library ($.ajax, $.get, $.post, $.getJSON) and moved under app.request method with same functionality and API:

  • $.ajax(parameters) -> app.request(parameters)
  • $.get(...) -> app.request.get(...)
  • $.post(...) -> app.request.post(...)
  • $.getJSON(...) -> app.request.json(...)
  • $.ajaxSetup(...) -> app.request.setup(...)

Init App

In v1 we init app using new Framework7 declaration and passing all possible parameters here. In v2 not much changed, except that now components related parameters are now "grouped" and must be passed in separate parameters properties.

So, if in v1 we had and app with such parameters:

var app = new Framework7({
  material: true, // enabled material theme
  cache: false,
  tapHold: true,
  uniqueHistory: true,
  pushState: true,
  panelLeftBreakpoint: 768,
  swipePanel: 'left',
  modalTitle: 'My App',
  popupCloseByOutside: true,
  smartSelectOpenIn: 'popup',
  smartSelectSearchbar: true,
  hideNavbarOnPageScroll: true,
  scrollTopOnNavbarClick: true,
  imagesLazyLoadThreshold: 50,
  statusbarOverlay: true,
  scrollTopOnStatusbarClick: true,
});

In v2 it will be :

var app = new Framework7({
  theme: 'md',
  routes: [
    /* ... */
  ],
  touch: {
    tapHold: true,
  },
  view: {
    xhrCache: false,
    pushState: true,
    uniqueHistory: true,
  },
  panel: {
    leftBreakpoint: 768,
    swipe: 'left',
  },
  dialog: {
    title: 'My App',
  },
  popup: {
    closeByBackdropClick: true,
  },
  smartSelect: {
    openIn: 'popup',
    searchbar: true,
  },
  navbar: {
    hideOnPageScroll: true,
    scrollTopOnTitleClick: true,
  },
  lazy: {
    threshold: 50,
  },
  statusbar: {
    overlay: true,
    scrollTopOnClick: true,
  },
});

Common app parameters like theme in the above example can be found in App Parameters documentation. Components related parameters can be found on each component page: Popup, Navbar, View, Panel, etc.

Router & Routes

Well, this is some absolutely new and totally reworked in v2.

How the routing works in v1: when we click on any link, then Router will load page by XHR request to url specified in link's href attribute. So if we click a link <a href="about.html">About Page</a> , router will load page from about.html file.

In v2 thins are totally different. When we click a link (or use router's api to load a page), it will first check what Route matches to link's url specified in href tag (or passed url in router api call), and then decides how to load the page for this link based on route parameters.

So first of all, we must pass app routes on app init. For example:

// Init App
var app = new Framework7({
  // Pass app routes on app init*
  routes: [
    {
      path: '/about/',
      url: './pages/about.html',
    },
    {
      path: '/news/',
      url: './pages/news.html',
    },
    {
      path: '/people/',
      componentUrl: './pages/people.html'
    },
    {
      path: '/users/:userId/',
      componentUrl: './pages/user.html',
    }
  ],
  // other app parameters
  ...
})

What does it mean? According to routes specified above:

  • When we click on link with /about/ href attribute, page will be loaded from /pages/about.html file
  • When we click on link with /news/ href attribute, page will be loaded from /pages/news.html file
  • When we click on link with /people/ href attribute, page will be loaded from /pages/people.html file as a Router Component
  • When we click on link with /users/25/ href attribute, page will be loaded from /pages/user.html file as a Router Component and it will receive userId: 25 route paremeter

That was the basics. There is much more to learn about v2 Router. Here is what is recommended to read/check:

What is Next?

This was the basic guide to migrate your app made with Framework7 v1 to v2. Of course there are a lot more new features which are out of the scope for this guide. As next steps it is highly recommended to check all new Framework7 v2 Docs and Framework7 v2 Starter Templates. And don't forget about Framework7 Forum - the best place to get F7 support.