【问题标题】:Converting Responsive Grid Layout to Plotly Dash将响应式网格布局转换为 Plotly Dash
【发布时间】:2021-02-09 15:16:50
【问题描述】:

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

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

由于我没有使用 react.js 的经验,我很困惑我应该做哪些修改才能将此组件转换为 Plotly Dash。

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

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
};

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

问候, 莱昂纳多

【问题讨论】:

    标签: javascript reactjs plotly-dash react-grid-layout


    【解决方案1】:

    实现自定义组件

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

    使用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,
    };
    

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

    要创建和编辑您的自定义组件,您需要按照说明设置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 组件生成的组件,看起来像这样:

    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)
    

    您也可以随意编辑。

    【讨论】:

    • 嗨,Bas,非常感谢您的回答,哑光!那么,根据您的示例,我可以假设我不需要声明所有组件功能吗?我的意思是,只有 setProps 就足够了?另外,在我作为参考的另一个组件上,我注意到创建者需要创建函数来更改状态等等......你可以看到我在这里提到的内容:github.com/AlgorithmHub/dash-responsive-grid-layout/blob/master/…;注意有onLayoutChange、on BreakpointChange等设置。
    • 是的,react-grid-layout 库可以处理自己组件的定义,您可以随意使用它们。一般来说,我会为您的自定义组件包括setPropsid。该链接是使用react-grid-layout 的可能实现的一个很好的示例,但它不一定是您的实现。如果您觉得不需要为您的用例处理onChangeLayout,或者您想以不同的方式处理它,您可以这样做。如果您确实想处理onChangeLayout 之类的道具,我认为您的链接提供了一种处理它的好方法。
    猜你喜欢
    • 2015-08-05
    • 2012-10-01
    • 1970-01-01
    • 2012-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-28
    • 1970-01-01
    相关资源
    最近更新 更多