Search code examples
javascriptwebix

Trying to change the Webix Jetpack layout dynamically


Hi I'm trying to build a dynamic user preference interface in Webix jetpack. When user click the layout change button I want to change the layout of the interface dynamically by making the views in in the id: "user" to display as rows. How can I achieve this. I tried several reconstructions methods but got fail. I user webix jetpack to build the page and its components.

import { JetView } from "webix-jet";
import UserForm from "./forms/account.form";
import NofificationForm from "./forms/notification.form";
import ThemeForm from "./forms/theme.form";
import Profile from "./Profile";
import PrivacyForm from "./forms/privacy.form";

export default class Preference extends JetView {
  config() {
    return {
      id: "a1",
      rows: [
        {
          view: "button",
          value: "Switch Layout",
          click: () => this.switchLayout(),
        },
        {
          responsive: "a1",
          id: "user",
          cols: [
            Profile,
            {
              view: "scrollview",
              scroll: "y",
              body: {
                rows: [UserForm, NofificationForm, ThemeForm, PrivacyForm],
              },
            },
          ],
        },
      ],
    };
  }

  switchLayout() {
    const layout = this.getRoot();
    const userView = layout.queryView({ id: "user" });

    // Check the current layout state and toggle it
    if (this.isLayoutColumns) {
      // Change to rows layout
      userView.config.cols = [];
      userView.config.rows = [
        Profile,
        {
          view: "scrollview",
          scroll: "y",
          body: {
            rows: [UserForm, NofificationForm, ThemeForm, PrivacyForm],
          },
        },
      ];
    } else {
      // Change to columns layout
      userView.config.rows = [];
      userView.config.cols = [
        Profile,
        {
          view: "scrollview",
          scroll: "y",
          body: {
            rows: [UserForm, NofificationForm, ThemeForm, PrivacyForm],
          },
        },
      ];
    }

    // Update the layout state
    this.isLayoutColumns = !this.isLayoutColumns;

    // Reconstruct the layout
    layout.reconstruct();
  }
}

Solution

  • since you are using Jet, there is a better option.

    1. Responsive layouts

    In the complex applications with Webix UI you will need to create a separate UI layout for different types of screens anyway (considering also the responsivity on mobile/different modes of appearance). To do so, Webix Jet provides a possibility either to set the app size and/or decide which part of the UI will be rendered depending on some condition. The same can be implemented with any desirable framework.

    For a detailed explanation and example please check the following Jet article.

    Here's also a basic example of a responsive Jet application (if you resize the demo, the layout will switch between two modes: full and compact):

    https://snippet.webix.com/knv80ah9

    1. Changing the layout on demand

    In this very example, you can see how I used the same technique to change the layout on demand. It can be a different layout and a different setting, not compact, here I reused it for the sake of simplicity. The main points are:

    • use app config to set a flag or a mode (this.app.config.mode = "rows" // or "columns", for example)
    • call JetView.refresh() or JetApp.refresh() to rerender the UI accordingly

    Note: Avoid using id in Jet. Use localId. Using id can result in nasty bugs due to view reuse and non-unique IDs. localId is visible only within one file and there is no need to make it unique. So:

    // before
    id: "user"
    ...
    const layout = this.getRoot();
    const userView = layout.queryView({ id: "user" });
    
    // after
    localId: "user"
    ...
    const userView = this.$$("user");