将响应式网格布局转换为 Plotly Dash [英] Converting Responsive Grid Layout to Plotly Dash

查看:88
本文介绍了将响应式网格布局转换为 Plotly Dash的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一个非常活跃的 Dash 用户,我开始发现我的 Dash 使用有很多限制,我意识到关于如何将组件转换为 dash 的信息/内容绝对有限,有过时且非常简单的例子... 而且我几乎没有任何 Javascript 或 React 知识,我完全不知道如何转换组件.

我正在尝试将响应式网格布局组件从 react.js 转换为 Plotly Dash,但我不知道在这种情况下我应该如何处理这些属性?组件链接:https://github.com/STRML/react-网格布局/blob/master/lib/ResponsiveReactGridLayout.jsx

由于我对 react.js 没有经验,所以我不知道应该做哪些修改才能将此组件转换为 Plotly Dash.

对于上面的组件,我应该只在Proptypes上声明Properties(如下所示)还是需要做更多的修改?

ResponsiveReactGridLayout.propTypes{////基础道具//类名:PropTypes.string,风格:PropTypes.object,//这可以显式设置.如果没有设置,它会自动//设置为容器宽度.请注意,调整大小将*不会*导致此调整.//如果您需要该行为,请使用 WidthProvider.宽度:PropTypes.number,//如果为 true,容器高度会膨胀并收缩以适应内容自动大小:PropTypes.bool,//列数.cols: PropTypes.number,//不可拖动的选择器.draggableCancel: PropTypes.string,//可拖动处理程序的选择器draggableHandle: PropTypes.string,//已弃用VerticalCompact:函数(道具:道具){如果 (props.verticalCompact === false &&process.env.NODE_ENV !== "生产";){控制台警告(//eslint-disable-line 无控制台 上的verticalCompact"已弃用,很快将被删除."+'使用`compactType`:水平";|垂直"|空值.');}},//选择垂直或hotizontal压实紧凑型:PropTypes.oneOf([垂直",水平"]),//布局是一个对象数组,格式为://{x: Number, y: Number, w: Number, h: Number, i: String}布局:功能(道具:道具){var layout = props.layout;//我希望你在网格项上设置数据网格属性如果(布局 === 未定义)返回;require("./utils").validateLayout(layout, "layout");},////网格尺寸////项目 [x, y] 之间的边距,单位为 px边距:PropTypes.arrayOf(PropTypes.number),//在容器内填充 [x, y],单位为 pxcontainerPadding: PropTypes.arrayOf(PropTypes.number),//行具有静态高度,但您可以根据需要根据断点更改此高度rowHeight: PropTypes.number,//默认无穷大,但如果您愿意,可以在此处指定最大值.//请注意,这不是完全充实的,如果您指定一个布局,则不会出错//超出行容量.但是,它不允许用户拖动/调整大小//穿过障碍物的项目.不过,他们可以将物品推到障碍物之外.//由于这个原因,故意没有记录下来.maxRows: PropTypes.number,////标志//isBounded: PropTypes.bool,isDraggable: PropTypes.bool,isResizable: PropTypes.bool,//如果为 true,则网格项在拖动时不会改变位置.防止碰撞:PropTypes.bool,//使用 CSS 变换而不是顶部/左侧使用CSSTransforms: PropTypes.bool,//父布局变换比例transformScale: PropTypes.number,//如果为true,外部元素可以以特定的网格位置作为参数触发onDrop回调isDroppable: PropTypes.bool,//调整手柄选项的大小调整大小手柄:调整大小手柄类型,调整大小手柄:调整大小手柄类型,////回调////回调,以便您可以保存布局.每次拖动后调用调整大小停止.onLayoutChange: PropTypes.func,//拖动开始时调用.回调是签名(layout、oldItem、newItem、placeholder、e、?node).//下面的所有回调都具有相同的签名.开始"和停止"回调省略了占位符".onDragStart: PropTypes.func,//调用每个拖动动作.onDrag: PropTypes.func,//拖动完成时调用.onDragStop: PropTypes.func,//调整大小开始时调用.onResizeStart: PropTypes.func,//当调整大小移动发生时调用.onResize: PropTypes.func,//调整大小完成时调用.onResizeStop: PropTypes.func,//当某些元素被删除时调用.onDrop: PropTypes.func,////其他验证//dropItem: PropTypes.shape({i: PropTypes.string.isRequired,w: PropTypes.number.isRequired,h: PropTypes.number.isRequired}),//孩子不能有重复的键.孩子:功能(道具:道具,道具名称:字符串){var children = props[propName];//检查子键是否重复.发现就扔.var 键 = {};React.Children.forEach(children, function (child) {如果(键[child.key]){抛出新错误('重复的子键'+child.key +'"成立!这将导致 ReactGridLayout 出现问题.);}键[child.key] = true;});},//用于获取包装 div 引用的可选 ref.内部引用:PropTypes.any};

非常欢迎任何帮助或参考...

问候,莱昂纳多

解决方案

实现自定义组件

如果您只想使用带有通过 npm 提供的包的库中的组件(例如 react-grid-layout),则无需重新-实现这些库中的组件.您可以简单地使用 npm 安装它们并在您的自定义组件中使用它们.

使用 ResponsiveGridLayout 的示例组件 (src/lib/components/GridLayout.react.js):

import React, {Component} from 'react';从 'prop-types' 导入 PropTypes;从'react-grid-layout'导入RGL,{WidthProvider};导入'../../../node_modules/react-grid-layout/css/styles.css';导入'../../../node_modules/react-resizable/css/styles.css';const ResponsiveGridLayout = WidthProvider(RGL);导出默认类 GridLayout 扩展组件 {使成为() {const {id, setProps} = this.props;常量布局 = [{x: 0, y: 0, w: 3, h: 3, i: 'a'},{x: 0, y: 1, w: 3, h: 3, i: 'b'},];返回 (<div id={id}><ResponsiveGridLayout rowHeight={30}>{layout.map((item) => (<div key={item.i} data-grid={item}><span>{item.i}</span>

))}</ResponsiveGridLayout>

);}}GridLayout.defaultProps = {};GridLayout.propTypes = {/*** 用于在 Dash 回调中标识此组件的 ID.*/id: PropTypes.string,/*** 应调用以报告属性更改的 Dash 分配的回调* 到 Dash,使它们可用于回调.*/setProps: PropTypes.func,};

环境设置(如果您已经完成,请跳过)

要创建和编辑自定义组件,您需要按照说明设置 cookiecutter dash-component-boilerplate.

但是要重申几个要点中所说的内容,您需要:

  • 安装cookiecutter:pip install cookiecutter
  • 运行 cookiecutter https://github.com/plotly/dash-component-boilerplate.git.这将生成您可以创建自定义组件的环境.
  • 填写您希望自定义组件的名称后,将目录更改为根据您提供的名称生成的目录.我选择了名称grid_layout,如果在cookiecutter提示后选择不同的值,你的结构会有所不同.
  • 此时您需要通过运行pip install -r requirements.txt来安装所需的python依赖项.您现在还可以使用 npm i react-grid-layout 安装 react-grid-layout.

基本用法

安装完所有内容后,我们可以编辑 src/lib/components 目录中的自定义组件.当我们进行了一些更改(用上面列出的代码替换了示例代码)并且我们感到满意时,我们可以运行 npm run build 来保留更改.

在此之后,您可以运行 python usage.py 并且您使用自定义组件的仪表板应用程序将运行.

usage.py 是一个常规的 Dash 应用程序,它导入在构建过程之后从 react 组件生成的组件,并且可以查看像这样:

导入 grid_layout导入破折号从 dash.dependencies 导入输入,输出将 dash_html_components 导入为 htmlapp = dash.Dash(__name__)app.layout = html.Div([grid_layout.GridLayout(id="grid-layout")])如果 __name__ == __main__":app.run_server(调试=真)

您也可以随意编辑.

I'm a very active Dash user and I have started to find a lot of limitations in my Dash usage and I realized that the information/contents about how converting components to dash are absolutely limited, with outdated and very simple examples... And I do not have almost any knowledge in Javascript or React, I'm completely lost on how to convert a component.

I'm trying to convert the Responsive Grid Layout component from react.js to Plotly Dash but I don't know how should I deal with the properties in this case? Link to the component: https://github.com/STRML/react-grid-layout/blob/master/lib/ResponsiveReactGridLayout.jsx

As I'm not experienced with react.js I'm confused about what modifications should I do to be able to convert this component to Plotly Dash.

In the case of the component above, should I only declare the Properties on the Proptypes (as shown below) or do I need to do more modifications?

ResponsiveReactGridLayout.propTypes{
  //
  // Basic props
  //
  className: PropTypes.string,
  style: PropTypes.object,

  // This can be set explicitly. If it is not set, it will automatically
  // be set to the container width. Note that resizes will *not* cause this to adjust.
  // If you need that behavior, use WidthProvider.
  width: PropTypes.number,

  // If true, the container height swells and contracts to fit contents
  autoSize: PropTypes.bool,
  // # of cols.
  cols: PropTypes.number,

  // A selector that will not be draggable.
  draggableCancel: PropTypes.string,
  // A selector for the draggable handler
  draggableHandle: PropTypes.string,

  // Deprecated
  verticalCompact: function (props: Props) {
    if (
      props.verticalCompact === false &&
      process.env.NODE_ENV !== "production"
    ) {
      console.warn(
        // eslint-disable-line no-console
        "`verticalCompact` on <ReactGridLayout> is deprecated and will be removed soon. " +
          'Use `compactType`: "horizontal" | "vertical" | null.'
      );
    }
  },
  // Choose vertical or hotizontal compaction
  compactType: PropTypes.oneOf(["vertical", "horizontal"]),

  // layout is an array of object with the format:
  // {x: Number, y: Number, w: Number, h: Number, i: String}
  layout: function (props: Props) {
    var layout = props.layout;
    // I hope you're setting the data-grid property on the grid items
    if (layout === undefined) return;
    require("./utils").validateLayout(layout, "layout");
  },

  //
  // Grid Dimensions
  //

  // Margin between items [x, y] in px
  margin: PropTypes.arrayOf(PropTypes.number),
  // Padding inside the container [x, y] in px
  containerPadding: PropTypes.arrayOf(PropTypes.number),
  // Rows have a static height, but you can change this based on breakpoints if you like
  rowHeight: PropTypes.number,
  // Default Infinity, but you can specify a max here if you like.
  // Note that this isn't fully fleshed out and won't error if you specify a layout that
  // extends beyond the row capacity. It will, however, not allow users to drag/resize
  // an item past the barrier. They can push items beyond the barrier, though.
  // Intentionally not documented for this reason.
  maxRows: PropTypes.number,

  //
  // Flags
  //
  isBounded: PropTypes.bool,
  isDraggable: PropTypes.bool,
  isResizable: PropTypes.bool,
  // If true, grid items won't change position when being dragged over.
  preventCollision: PropTypes.bool,
  // Use CSS transforms instead of top/left
  useCSSTransforms: PropTypes.bool,
  // parent layout transform scale
  transformScale: PropTypes.number,
  // If true, an external element can trigger onDrop callback with a specific grid position as a parameter
  isDroppable: PropTypes.bool,

  // Resize handle options
  resizeHandles: resizeHandlesType,
  resizeHandle: resizeHandleType,

  //
  // Callbacks
  //

  // Callback so you can save the layout. Calls after each drag & resize stops.
  onLayoutChange: PropTypes.func,

  // Calls when drag starts. Callback is of the signature (layout, oldItem, newItem, placeholder, e, ?node).
  // All callbacks below have the same signature. 'start' and 'stop' callbacks omit the 'placeholder'.
  onDragStart: PropTypes.func,
  // Calls on each drag movement.
  onDrag: PropTypes.func,
  // Calls when drag is complete.
  onDragStop: PropTypes.func,
  //Calls when resize starts.
  onResizeStart: PropTypes.func,
  // Calls when resize movement happens.
  onResize: PropTypes.func,
  // Calls when resize is complete.
  onResizeStop: PropTypes.func,
  // Calls when some element is dropped.
  onDrop: PropTypes.func,

  //
  // Other validations
  //

  droppingItem: PropTypes.shape({
    i: PropTypes.string.isRequired,
    w: PropTypes.number.isRequired,
    h: PropTypes.number.isRequired
  }),

  // Children must not have duplicate keys.
  children: function (props: Props, propName: string) {
    var children = props[propName];

    // Check children keys for duplicates. Throw if found.
    var keys = {};
    React.Children.forEach(children, function (child) {
      if (keys[child.key]) {
        throw new Error(
          'Duplicate child key "' +
            child.key +
            '" found! This will cause problems in ReactGridLayout.'
        );
      }
      keys[child.key] = true;
    });
  },

  // Optional ref for getting a reference for the wrapping div.
  innerRef: PropTypes.any
};

Any help or references are very welcome...

Regards, Leonardo

解决方案

Implementing the custom component

If you just want to use components from a library with a package available through npm (like react-grid-layout), you don't need to re-implement the components in these libraries. You can simply install them with npm and use them in your custom component.

Example component using ResponsiveGridLayout (src/lib/components/GridLayout.react.js):

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import RGL, {WidthProvider} from 'react-grid-layout';
import '../../../node_modules/react-grid-layout/css/styles.css';
import '../../../node_modules/react-resizable/css/styles.css';

const ResponsiveGridLayout = WidthProvider(RGL);

export default class GridLayout extends Component {
    render() {
        const {id, setProps} = this.props;
        const layout = [
            {x: 0, y: 0, w: 3, h: 3, i: 'a'},
            {x: 0, y: 1, w: 3, h: 3, i: 'b'},
        ];

        return (
            <div id={id}>
                <ResponsiveGridLayout rowHeight={30}>
                    {layout.map((item) => (
                        <div key={item.i} data-grid={item}>
                            <span>{item.i}</span>
                        </div>
                    ))}
                </ResponsiveGridLayout>
            </div>
        );
    }
}

GridLayout.defaultProps = {};

GridLayout.propTypes = {
    /**
     * The ID used to identify this component in Dash callbacks.
     */
    id: PropTypes.string,

    /**
     * Dash-assigned callback that should be called to report property changes
     * to Dash, to make them available for callbacks.
     */
    setProps: PropTypes.func,
};

Environment setup (Skip if you've already done this)

To create and edit your custom component you need to have followed the instructions to setup the cookiecutter dash-component-boilerplate.

But to re-iterate what is said in a couple of bullet points, you need to:

  • Install cookiecutter: pip install cookiecutter
  • Run cookiecutter https://github.com/plotly/dash-component-boilerplate.git. This will generate the environment where you can create your custom components.
  • After filling in the name you want your custom component to have you change directory into the directory generated based on the name you provided. I have chosen the name grid_layout, your structure will be different if you choose different values after being prompted by cookiecutter.
  • At this point you need to install the needed python dependencies by running pip install -r requirements.txt. You can now also install react-grid-layout using npm i react-grid-layout.

Basic usage

When everything is installed we can edit the custom component inside the src/lib/components directory. When we've made some change (replaced the example code with the code listed above) and we are satisfied we can run npm run build to persist the changes.

After this you can run python usage.py and your dash app using your custom component will be run.

usage.py is a regular Dash application that imports the component that is generated from the react component after the build process and can look something like this:

import grid_layout
import dash
from dash.dependencies import Input, Output
import dash_html_components as html

app = dash.Dash(__name__)

app.layout = html.Div([grid_layout.GridLayout(id="grid-layout")])


if __name__ == "__main__":
    app.run_server(debug=True)

You can also edit this as you like.

这篇关于将响应式网格布局转换为 Plotly Dash的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆